标签:
1
题目大意:首先是T组数据,之后每组第一行是N M K,表示N个城市,M条路的信息,和
已经连接上的K个城市信息。接下来M行每行是城市A到B建路需要的花费。再接下来K行每
行第一个数为t,之后t个数表示已经连接在一起的城市。简单说,就是给你N个城市和M条
路的花费,再给你已经联通的城市,求连接所有城市的最小生成树总权值是多少。
思路:用kruskal算法来做,先把联通的城市并入集合,再依次并入边权值最小的边,直到
并到N-1条边,就生成了最小生成树。如果并完了没有达到N-1条边,就是不能联通,输出
"-1"。这道题昨天写的,提交了23次,不是TLE就是栈溢出,最后发现:把cin改为scanf,
再把sort改为qsort就不超时了。。。前边的我理解,后边的就比较无语了。。。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct Node
{
int from;
int to;
int w;
}Edges[25500];
int father[550],ans;
int find(int x)
{
int root = x;
while(root != father[root])
{
root = father[root];
}
int z;
while(x != root)
{
z = father[x];
father[x] = root;
x = z;
}
return root;
}
//bool cmp(Node a,Node b)
//{
// return a.w < b.w;
//}
int cmp(const void * a, const void * b)
{
return ((Node *)a)->w - ((Node *)b)->w;
}
bool Kruskal(int N,int M,int k)
{
// sort(Edges,Edges+M,cmp);
qsort(Edges,M,sizeof(Node),cmp);
int x,y;
for(int i = 0; i < M; i++)
{
x = find(Edges[i].from);
y = find(Edges[i].to);
if(x != y)
{
father[y] = x;
k++;
ans += Edges[i].w;
if(k == N-1)
return true;
}
}
if(k == N-1)
return true;
else
return false;
}
int main()
{
int T,k,t,a,b,N,M,K;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&N,&M,&K);
for(int i = 1; i <= N; i++)
father[i] = i;
for(int i = 0; i < M; i++)
{
scanf("%d%d%d",&Edges[i].from,&Edges[i].to,&Edges[i].w);
}
k = 0,ans = 0;
for(int i = 0; i < K; i++)
{
scanf("%d%d",&t,&a);
a = find(a);
t--;
while(t--)
{
scanf("%d",&b);
b = find(b);
if(a != b)
{
father[b] = a;
k++;
}
}
}
if(Kruskal(N,M,k))
printf("%d\n",ans);
else
printf("-1\n");
}
return 0;
}
HDU3371 Connect the Cities【Kruskal】
标签:
原文地址:http://blog.csdn.net/lianai911/article/details/42174473