还是畅通工程(最小生成树 Kruskal)
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
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
Huge input, scanf is recommended.
最小生成树Kruskal算法的步骤:
1. 初始化所有节点的父亲(我的pre数组)都是他本身,即都是独立的节点。
2. 对所有边排序,从小到大遍历:
若当前边两个节点不在一个集合(“首领”不同,pre数组的值不同),那就放在一个集合里(首领达成一致,修改其中一个节点的pre成另一个的即可);
若在同一集合,不操作,看下一条边。
3. 最终若所有点在同一集合,得到最小生成树。
1 #include <iostream> 2 #include <algorithm> 3 4 #define MAX 105 5 6 using namespace std; 7 8 struct node 9 { 10 int a, b, cost; 11 bool operator < (const node & A) const{ 12 return cost < A.cost; 13 } 14 }str[10005]; 15 16 int pre[105]; 17 18 int find_pre(int x) 19 { 20 if(x==pre[x]) return x; 21 else return pre[x] = find_pre(pre[x]); 22 } 23 24 int main() 25 { 26 int n, i, a, b, m; 27 while(cin >> n && n) 28 { 29 for(i = 0; i < MAX; i++) 30 { 31 pre[i] = i; 32 } 33 m = n * (n-1) / 2; 34 for(i = 0; i < m; i++) 35 { 36 cin >> str[i].a >> str[i].b >> str[i].cost; 37 } 38 sort(str, str + m); 39 int re = 0; 40 for(i=0; i<m; i++) 41 { 42 a = find_pre(str[i].a); 43 b = find_pre(str[i].b); 44 if(a!=b) 45 { 46 pre[a] = b; 47 re += str[i].cost; 48 } 49 } 50 cout << re << endl; 51 } 52 return 0; 53 }