还是畅通工程
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
Input测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
Output对每个测试用例,在1行里输出最小的公路总长度。
Sample Input
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
Sample Output
3
5
题目大意 : 求让各地连接起来的最小带权路径。
题目分析 : 其实这道就是一个排序就可以解决的问题了,按从小到大的顺序排好,在循环遍历查找并连通起来,同时sum记录花费的路数,如果连接好了,则退出循环。
有几点注意一下就好了,find()函数用路径压缩,好处理一些。union的时候,就已经开始判断是否连接了,连接就跳过。
题目收获 : 带权路径的最小生成树kruskal算法。
AC代码 :
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define maxn 10000 using namespace std; int per[maxn],sum; struct quan_road { int first,second; int instance; }; quan_road as[maxn]; bool cmp(quan_road x,quan_road y) { return x.instance<y.instance; } void makeSet(int n) { memset(per,0,sizeof(per)); for(int i=1;i<=n;i++) per[i]=i; } int FindSet(int x) { if(x!=per[x]) { per[x] = FindSet(per[x]); } return per[x]; } void unionSet(int x,int y,int z) { int a=FindSet(x); int b=FindSet(y); if(a!=b) per[b]=a,sum+=z; } int main() { int n; while(true) { cin >> n; if(n==0) break; makeSet(n); memset(as,0,sizeof(as)); int a,b,way; for(int i=0;i<n*(n-1)/2;i++) { cin >> a >> b >> way; as[i].first=a,as[i].second=b,as[i].instance=way; } sort(as,as+n*(n-1)/2,cmp); sum=0; for(int i=0;i<n*(n-1)/2;i++) { unionSet(as[i].first,as[i].second,as[i].instance); } cout << sum << endl; } return 0; }