Problem Description
在一个无向图中,求最小生成树。
Input
多组测试数据,对于每组测试数据,第1行输入正整数n(1 <= n <= 1000)、m,表示n个顶点(编号从1开始)和m条边。之后m行每行输入u(1 <= u <= n)、v(1 <= v <= n)、w(1 <= w <= 100),表示在顶点u和顶点v之间存在无向边,且权值为w。
Output
对于每组测试数据,若存在最小生成树则输出最小生成树的权值和,若不存在最小生成树则输出-1。
Sample Input
3 7 1 2 19 2 3 11 3 1 7 1 3 5 2 3 89 3 1 91 1 2 32
Sample Output
16
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int f[1200];
struct node
{
int u,v,w;
}e[120000];
int cmp(struct node a,struct node b)
{
return a.w<b.w;
}//按路径权值排序
int getf(int a)
{
if(f[a]==a)
{
return a;
}
f[a]=getf(f[a]);
return f[a];
}//并查集查找父节点
int bingchaji(int a,int b)
{
int t1,t2;
t1=getf(a);
t2=getf(b);
if(t1!=t2)//判断两点是否在同一个集合中
{
f[t2]=t1;
return 1;//表明未连接
}
return 0;
}//并查集合并
int main()
{
int n,m,i,sum,num;
while(scanf("%d %d",&n,&m)!=EOF)
{
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w);
}
sort(e+1,e+m+1,cmp);//从小到大排序
for(i=1;i<=n;i++)
{
f[i]=i;
}//并查集初始化
num=0;sum=0;
//kruskal核心代码
for(i=1;i<=m;i++)
{
if(bingchaji(e[i].u,e[i].v))//判断是否已经在一个集合中
{
num++;
sum+=e[i].w;
}
if(num==n-1)
break;
}
if(num!=n-1)//当不存在最小生成树的时候
{
printf("%d\n",-1);
}
else
{
printf("%d\n",sum);
}
}
return 0;
}