题目:http://acm.hdu.edu.cn/showproblem.php?pid=3371
解题思路:题目要我们在已经有的一部分点相连的情况下求最小生成树。首先用并查集将所有城市分离成一个独立的点
然后用已经存在的路去连接一部分点,使其构成一棵树,然后用Kruskal 算法 贪心求出最小生成树。
实现代码如下:
#include<stdio.h> #include<algorithm> struct road { int x,y; int w; }a[25010]; int per[510]; int cmp(const void *a,const void *b) { if(((road*)a)->w != ((road*)b)->w) return ((road*)a)->w > ((road*)b)->w ? 1 : -1; return 0; } int find(int x) { int r; r = x; while(r != per[r])//查找根结点 r = per[r]; while( per[x] != r) { per[x] = r; x = r; } return r; } int main() { int T,n,m,k,t,c,b,root,Min; int i,j; scanf("%d",&T); while( T-- ) { scanf("%d%d%d",&n,&m,&k); for(i = 0; i < m; i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w); qsort(a,m,sizeof(road),cmp); // for(i = 0; i < m; i++) // printf("%d %d %d\n",a[i].x,a[i].y,a[i].w); for(i = 0; i <= n; i++) per[i] = i; for(j =0; j < k ;j++) { scanf("%d",&t); scanf("%d",&c); root = find(c); for(i = 1; i < t; i++) { scanf("%d",&c); c = find(c); if(c != root) { n --; per[c] = root; } } } // printf("%d\n",n); Min = 0; for(i = 0; i < m && n > 1 ; i++) { c = find(a[i].x); b = find(a[i].y); if(c != b) { n --; per[c] = b; Min += a[i].w; } } // printf("%d\n",n); if(n > 1) printf("-1\n"); else printf("%d\n",Min); } return 0; }