HDU 1102 Constructing Roads
http://acm.hdu.edu.cn/showproblem.php?pid=1102
题意:
有N个村庄,编号从1到N,你应该建立一些道路,使每两个村庄可以连接到彼此。我们说两个村庄A和B连接,当且仅当在A和B之间有道路,或者存在一个村庄C,使得在A和C之间有道路,并且C和B连接。
我们知道,一些村庄之间已经有一些道路,你的工作是建造一些道路,使所有的村庄都连接,所有建设的道路的长度是最小的。
我们知道,一些村庄之间已经有一些道路,你的工作是建造一些道路,使所有的村庄都连接,所有建设的道路的长度是最小的。
思路:
普里姆算法或克鲁斯卡尔算法。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn = 100 + 5; 7 8 int n, cnt, ans; 9 10 //边 11 struct node 12 { 13 int u; //边的起点 14 int v; //边的终点 15 int w; //边的权重 16 }edge[maxn*maxn]; 17 18 int p[maxn]; 19 20 int find(int x) 21 { 22 return p[x] == x ? x : find(p[x]); 23 } 24 25 bool cmp(node a, node b) 26 { 27 return a.w < b.w; 28 } 29 30 void Kruskal() 31 { 32 //首先按权重从小到大排序 33 sort(edge, edge + cnt, cmp); 34 //依次选择权重小的 35 for (int i = 0; i < cnt; i++) 36 { 37 int x = find(edge[i].u); 38 int y = find(edge[i].v); 39 //如果没有添加,就添加上去 40 if (x == y) continue; 41 ans += edge[i].w; 42 p[x] = y; 43 } 44 } 45 46 int main() 47 { 48 //freopen("D:\\txt.txt", "r", stdin); 49 while (cin >> n) 50 { 51 for (int i = 1; i <= n; i++) 52 p[i] = i; 53 cnt = 0; 54 for (int i = 1; i <= n;i++) 55 for (int j = 1; j <= n; j++) 56 { 57 edge[cnt].u = i; 58 edge[cnt].v = j; 59 cin >> edge[cnt].w; 60 cnt++; 61 } 62 int m; 63 int a, b; 64 cin >> m; 65 while (m--) 66 { 67 cin >> a >> b; 68 int x = find(a); 69 int y = find(b); 70 p[x] = y; 71 } 72 ans = 0; 73 Kruskal(); 74 cout << ans << endl; 75 } 76 return 0; 77 }