九度oj-1017

题目描述:

某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。

输入:

测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。

输出:

对每个测试用例,在1行里输出最小的公路总长度。

样例输入:

3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0

样例输出:

3
5

代码:

Kruskal

#include <iostream>  
#include <algorithm>  
using namespace std;  
struct Node  
{  
int startPoint;  
int endPoint;  
int length;  
} nodes[5000];  
bool cmp(const Node A,const Node B)  
{  
return A.length<B.length;  
}  
int father[100];  
int findSet(int num)  
{  
//其实就是获取到分组的最初始的点的信息;  
if(father[num]!=num)  
    return findSet(father[num]);  
else          
    return father[num];  
}  
bool UnionSet(int x,int y)  
{  
int tmpx=findSet(x);  
int tmpy=findSet(y);  
if(tmpy==tmpx)//因为两个已经是一个组了;  
    return false;  
father[tmpy]=tmpx;//如果可以合并,这里只需要更新其前驱节点,因为他最终还是会找到之前的组;  
return true;  


}  
int main()  
{  
int num;  
while(cin>>num&&num)  
{  
    for(int i=1;i<=num;i++)  
        father[i]=i;  
    int tmp=num*(num-1)/2;  
    for (int i=0;i<tmp;i++)  
        cin>>nodes[i].startPoint>>nodes[i].endPoint>>nodes[i].length;  
    sort(nodes,nodes+tmp,cmp);  
    int result=0,count=0;  
    for (int i=0;i<tmp;i++)  
    {  
        if(UnionSet(nodes[i].startPoint,nodes[i].endPoint))  
        {  
            result=result+nodes[i].length;  
            count++;  
            if(count+1==num)  
                break;  
        }  
    }  
    cout<<result<<endl;  
}  
return 0;  
}  

Prim 可以和Dijkstra对比,会发现惊人的相似,Dijkstra只是多维护了一个点到点的距离,而Prim只需要维护最短距离

#include <iostream>  
#include <algorithm>  
using namespace std;  
int A[100][100],low[100];  
bool visited[100];  
int MaxInt=1232000;  
int Prim(int num)  
{  
int minDis,result=0;  
int ppre=1;  
for (int i=1;i<=num;i++)  
{  
    low[i]=A[1][i];  
}  
visited[ppre]=true;  
for (int i=1;i<num;i++)  
{  
    minDis=MaxInt;  
    for (int j=1;j<=num;j++)//找到最小;  
    {  
        if(!visited[j]&&low[j]<minDis)  
        {  
            minDis=low[j];  
            ppre=j;  
        }  
    }  
    result=result+minDis;  
    for (int j=1;j<=num;j++)  
    {  
        if(!visited[j]&&A[ppre][j]<low[j])  
            low[j]=A[ppre][j];  
    }  
    visited[ppre]=true;  
}  
return result;  
}  
int main()  
{  
int num;  
while(cin>>num&&num)  
{  
    for(int i=1;i<=num;i++)  
    {  
        visited[i]=false;  
        for (int j=1;j<=num;j++)  
        {  
            A[i][j]=MaxInt;  
        }  
    }  
    int tmp=num*(num-1)/2,x,y,z;  
    for (int i=0;i<tmp;i++)  
    {  
        cin>>x>>y>>z;  
        A[y][x]=A[x][y]=z;  
    }  
    cout<<Prim(num)<<endl;  
}  
return 0;  
}