还是畅通工程
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 30823 Accepted Submission(s): 13828
Problem Description
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
当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
Hint
Hint
Source
浙大计算机研究生复试上机考试-2006年
//并查集实现kruskal算法;
1 #include <stdio.h> 2 #include <algorithm> 3 int father[110]; 4 using namespace std; 5 6 struct vilage 7 { 8 int a,b,c; 9 }; 10 vilage num[5000]; 11 12 bool cmp(vilage a, vilage b) 13 { 14 return a.c < b.c ; 15 } 16 17 int find(int a) 18 { 19 while(father[a]!=a) 20 a = father[a]; 21 return a; 22 } 23 24 int mercy (int a, int b) 25 { 26 a=find(a) ; 27 b=find(b) ; 28 if(a != b) 29 { 30 father[a] = b ; 31 return 1; 32 } 33 return 0; 34 } 35 36 int main() 37 { 38 int n; 39 while(~scanf("%d",&n),n) 40 { 41 int i; 42 for(i=1; i<=n; i++) 43 father[i]=i ; 44 45 n=n*(n-1)/2 ; 46 for(i=1;i<=n;i++) 47 scanf("%d %d %d",&num[i].a, &num[i].b, &num[i].c); 48 sort(num+1,num+n+1,cmp); 49 50 int total=0 ; 51 for(i=1; i<=n; i++) 52 { 53 if(mercy(num[i].a, num[i].b)) 54 total+=num[i].c ; 55 } 56 printf("%d ",total); 57 } 58 return 0; 59 }
//Prime() 算法;
/*看上图,假设我们从节点1开始寻找(其实上面的程序就是这么干的,当然你可以假设从任意一个节点开始)。进入循环后,第一个for表示以某个节点 为基准(注意这个某个是以前已经找到的符合条件的),第二个for表示在基准点的基础上,寻找与基准点相连并且权值最小的(权值的意思就是上图线上的数字)。 简单模拟一下:从1开始,则通过第二个for可以发现1->2权值最小。所以把2节点加进set。然后分别以1和2为基准点,寻找与之相连的权值最小的点,找到后加入set,对了 ,找到后别忘了把该节点标记为以符合,即对vis操作。就是这样循环,当道while中cur==n了,也就是说已经找玩n个点了,这时的值就是结果了。*/
1 #include <stdio.h> 2 #include <string.h> 3 int map[1010][1010]; 4 int vis[1010]; //标记点是否已经被选 ; 5 int s[1010]; //符合要求的点的集合; 6 int n; 7 int prim() 8 { 9 int cur=0, y, min, sum = 0; 10 s[++cur] = 1; 11 vis[cur] = 1; 12 while(cur < n) 13 { 14 min = 1000000; 15 for(int i = 1; i<=cur; i++) 16 { 17 for(int j = 1; j<=n; j++) 18 { 19 if(!vis[j] && map[s[i]][j] < min) 20 { 21 min = map[s[i]][j]; 22 y = j; 23 } 24 } 25 } 26 sum += min; 27 vis[y] = 1; 28 s[++cur] = y; 29 } 30 return sum; 31 } 32 int main() 33 { 34 int m; 35 while(~scanf("%d", &n), n) 36 { 37 memset(vis, 0, sizeof(vis)); 38 memset(s, 0, sizeof(s)); 39 m = n * (n-1) / 2; 40 for(int i=0; i<m; i++) 41 { 42 int a, b, c; 43 scanf("%d %d %d", &a, &b, &c); 44 map[a][b] = map[b][a] = c; 45 } 46 int sum = prim(); 47 printf("%d ", sum); 48 } 49 return 0; 50 }