题目: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;
}