HDU 5253 连接的管道(Kruskal算法求解MST)
题目:
老 Jack 有一片农田,以往几年都是靠天吃饭的。但是今年老天格外的不开眼,大旱。所以老 Jack 决定用管道将他的所有相邻的农田全部都串联起来,这样他就可以从远处引水过来进行灌溉了。当老 Jack 买完所有铺设在每块农田内部的管道的时候,老 Jack 遇到了新的难题,因为每一块农田的地势高度都不同,所以要想将两块农田的管道链接,老 Jack 就需要额外再购进跟这两块农田高度差相等长度的管道。
现在给出老 Jack农田的数据,你需要告诉老 Jack 在保证所有农田全部可连通灌溉的情况下,最少还需要再购进多长的管道。另外,每块农田都是方形等大的,一块农田只能跟它上下左右四块相邻的农田相连通。
现在给出老 Jack农田的数据,你需要告诉老 Jack 在保证所有农田全部可连通灌溉的情况下,最少还需要再购进多长的管道。另外,每块农田都是方形等大的,一块农田只能跟它上下左右四块相邻的农田相连通。
Input第一行输入一个数字T(T≤10)T(T≤10),代表输入的样例组数
输入包含若干组测试数据,处理到文件结束。每组测试数据占若干行,第一行两个正整数 N,M(1≤N,M≤1000)N,M(1≤N,M≤1000),代表老 Jack 有N行*M列个农田。接下来 N 行,每行 M 个数字,代表每块农田的高度,农田的高度不会超过100。数字之间用空格分隔。
Output对于每组测试数据输出两行:
第一行输出:"Case #i:"。i代表第i组测试数据。
第二行输出 1 个正整数,代表老 Jack 额外最少购进管道的长度。Sample Input
2 4 3 9 12 4 7 8 56 32 32 43 21 12 12 2 3 34 56 56 12 23 4
Sample Output
Case #1: 82 Case #2: 74
题意描述:
输入矩阵的大小,再输入矩阵
计算并输出连接这些高度不同的农田的所需要的最少管道长度
解题思路:
主要是题目数据的转化,可以将每块地进行编号,再用结构体将边的信息存起来,使用Kruskal算法即可。
代码实现:
1 #include<stdio.h> 2 #include<math.h> 3 #include<algorithm> 4 using namespace std; 5 struct edge 6 { 7 int u,v,w; 8 }; 9 int cmp(struct edge x,struct edge y) 10 { 11 return x.w<y.w; 12 } 13 struct edge e[1000*1000*2]; 14 int list[1010][1010],f[1010],map[1010][1010]; 15 16 int getf(int v); 17 int merge(int v,int u); 18 19 int main() 20 { 21 int T,n,m,i,j,k,tx,ty,q,p,t=0,c,sum; 22 scanf("%d",&T); 23 while(T--) 24 { 25 scanf("%d%d",&n,&m); 26 q=1; 27 for(i=1;i<=n;i++) 28 { 29 for(j=1;j<=m;j++) 30 { 31 scanf("%d",&map[i][j]); 32 list[i][j]=q++; 33 } 34 } 35 36 p=1; 37 for(i=1;i<=n;i++) 38 { 39 for(j=1;j<=m;j++) 40 { 41 tx=i; 42 ty=j+1; 43 if(!(tx<1 || tx >n || ty<1 || ty>m)) 44 { 45 e[p].u=list[tx][ty]; 46 e[p].v=list[i][j]; 47 e[p++].w=abs(map[tx][ty]-map[i][j]); 48 } 49 50 tx=i+1; 51 ty=j; 52 if(!(tx<1 || tx >n || ty<1 || ty>m)) 53 { 54 e[p].u=list[tx][ty]; 55 e[p].v=list[i][j]; 56 e[p++].w=abs(map[tx][ty]-map[i][j]); 57 } 58 } 59 } 60 61 sort(e+1,e+p,cmp); 62 for(i=1;i<=n*m;i++) 63 f[i]=i; 64 c=0; 65 sum=0; 66 for(i=1;i<p;i++) 67 { 68 if( merge(e[i].u,e[i].v) ) 69 { 70 c++; 71 sum += e[i].w; 72 } 73 if(c == n*m -1) 74 break; 75 } 76 printf("Case #%d:\n%d\n",++t,sum);//输出的时候先检查结果,再套格式 77 } 78 return 0; 79 } 80 81 int getf(int v) 82 { 83 if(f[v]==v) 84 return v; 85 else 86 { 87 f[v]=getf(f[v]); 88 return f[v]; 89 } 90 } 91 int merge(int v,int u) 92 { 93 int t1,t2; 94 t1=getf(v); 95 t2=getf(u); 96 if(t1 != t2) 97 { 98 f[t2]=t1; 99 return 1; 100 } 101 return 0; 102 }
易错分析:
1、使用三层循环很容易超时,在同学的提示下,优化了一下,不过还是有可能超时,需要将自定义函数放在主函数后面,另外也可以对并查集再进行优化一下
参考博文:http://blog.csdn.net/k_young1997/article/details/76590545
2、先检查答案,格式最后再修改。
欢迎交流,共同进步——