http://acm.hdu.edu.cn/showproblem.php?pid=1863
题意:求最小生成树。
思路:克鲁斯卡尔算法。
代码是自己根据对克鲁斯卡尔的理解写的,可能不够精简,所以仅供参考,不足为训,还望高人指点。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct ln
{
int a,b,c;
}con[10000];
int set[1000];
int cmp(const void *p,const void *q)
{
return (*(struct ln*)p).c>=(*(struct ln*)q).c?1:-1;
}
int find(int x)
{
while(set[x]!=x)
x=set[x];
return x;
}
void merge(int x,int y)
{
x=find(x);
y=find(y);
if(y<x)
set[x]=y;
else if(y>x)
set[y]=x;
}
main()
{
int n,m,i,t,use[1000],cost,cnt;
while(scanf("%d %d",&n,&m)&&n)
{
for(i=1;i<=m;i++)
{
set[i]=i;
}
memset(use,0,sizeof(use));
for(i=0;i<n;i++)
{
scanf("%d %d %d",&con[i].a,&con[i].b,&con[i].c);
}
qsort(con,n,sizeof(struct ln),cmp);
cost=0;
t=m;
for(i=0;i<n&&i<t-1;i++)
{
if(!use[con[i].a])
use[con[i].a]=1;
if(!use[con[i].b])
use[con[i].b]=1;
if(find(con[i].a)==find(con[i].b))//在同一连通分量
t++;
else
{
merge(con[i].a,con[i].b);
cost+=con[i].c;
}
}
for(cnt=0,i=1;i<=m;i++)
{
if(i==set[i])
cnt++;
}
if(cnt==1)
printf("%d\n",cost);
else
printf("?\n");
}
return 0;
}