本题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1863
解题思路:村庄(支点)之间修公路,给出之间需要的的修路费(权值),如果输入的统计数据不足的话,最后输出的时候输出“?”。这道题既可以用并查集解也可以用最小生成树求解,差不多都可以算是套模板的题,只是最后输出“?”的时候需要点技巧:
最小生成树代码:
1 #include <iostream> 2 #include <algorithm> 3 #define maxn 105 4 #define INF 999999 5 6 using namespace std; 7 int M, N;///M是村庄数、N是道路数 8 bool used[maxn]; 9 int cost[maxn][maxn]; 10 int mincost[maxn]; 11 12 int prim () { 13 for (int i = 1; i <= M; ++i) { 14 mincost[i] = INF; 15 used[i] = false; 16 } 17 mincost[1] = 0; 18 int res = 0; 19 while (true) { 20 int v = -1; 21 for (int u = 1; u <= M; ++u) { 22 if (!used[u] && (v == -1 || mincost[u] < mincost[v])) v = u; 23 } 24 if (v == -1) break; 25 if (mincost[v] == INF) return INF;///使用这种方法检查输出"?"的情况. 26 used[v] = true; 27 res += mincost[v]; 28 for (int u = 1; u <= M; ++u) { 29 mincost[u] = min (mincost[u], cost[v][u]); 30 } 31 } 32 return res; 33 } 34 35 int main () { 36 int a, b, w; 37 while ((cin >> N) && N ) { 38 // int flag = 0; 39 cin >> M; 40 for (int i = 1;i <= M; ++i) 41 for (int j = 1;j <= M; ++j) 42 cost[i][j] = INF; 43 for (int i = 1; i <= N; ++i) { 44 cin >> a >> b >> w; 45 cost[b][a] = cost[a][b] = w; 46 } 47 /* for (int i = 1; i <= M; ++i){ 48 for (int j = 1; j <= M; ++j) { 49 if (cost[i][j] == INF && i != j) 50 flag = 1; 51 }//一开始是用这种方法检查单独的点的,(错误) 52 }*/ 53 int res = prim (); 54 if (res == INF) 55 cout << "?" << endl; 56 else 57 cout << res << endl; 58 } 59 return 0; 60 }
最小生成树:在计算的时候做一个选择的点是否是正无穷的判断(如果一个点是孤立的话,当取到最后的时候会将代码中的v赋值到那个被孤立的点,那个点没有赋值权值,所以就是正无穷)。
并查集代码:
1 #include<cstdio> 2 #include<cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 int pre[200]; 8 struct road { //公路的结构体 9 int x, y, v; 10 }ad[6000]; 11 12 bool cmp(road a, road b) { 13 return a.v < b.v; 14 } 15 16 int find(int x) { //寻找 17 if(pre[x] != x) 18 return pre[x] = find(pre[x]); 19 return pre[x]; 20 } 21 22 int mix(int x,int y) { //合并 23 int fx = find(x), fy = find(y); 24 if(fx == fy) 25 return 0; 26 pre[fy] = fx; 27 return 1; 28 } 29 30 int main() { 31 int i, j, n, m; 32 int ans; 33 int count; 34 while(~scanf("%d%d",&m,&n)) { 35 if (m == 0) 36 break; 37 for(j = 0; j < m; j++) 38 scanf("%d%d%d",&ad[j].x ,&ad[j].y,&ad[j].v); 39 for(i = 0; i <= n; i++) 40 pre[i] = i; 41 ans = 0; 42 count = 0; 43 sort(ad, ad+m, cmp); 44 for(i = 0; i < m; ++i) { 45 if(count == n - 1) break; 46 if(mix(ad[i].x, ad[i].y)) { 47 ++ count; /////在这里判断输出"?"的时候 48 ans = ans + ad[i].v; 49 } 50 } 51 if(count != n - 1) 52 printf("?\n"); 53 else 54 printf("%d\n",ans); 55 } 56 return 0; 57 }
并查集:另外定义一个变量,在计算的时候自加,最后判断和“M - 1”(M是村庄的数目)的关系,因为离散的点连成一条线之间的道路条数就是M-1。
欢迎码友评论,一起成长。
原文:http://www.cnblogs.com/Ddlm2wxm/p/5719553.html