问题: 有n个点,m条边。求该图的最小生成树。 分析: 问题与上面链接里说的一样,只是解决方法变了。 Kruskal算法的实现主要靠并查集的思想,最终目的把所有点加入到一个几个集合
问题:
有n个点,m条边。求该图的最小生成树。
分析:
问题与上面链接里说的一样,只是解决方法变了。
Kruskal算法的实现主要靠并查集的思想,最终目的把所有点加入到一个几个集合里。
算法思想:
1、把存在的边按边长进行排序,从小到大。目的是从小的边开始遍历,以便找最小生成树
推荐用结构体存边,不要用邻接矩阵存关系
把n个点连接在一起,起始最少需要n-1跳变就够了。因此我们从那m条边里选出n-1条边就够了
2、遍历每一条边。应用并查集,查看每条边的两个端点之间是否相通,如果不相通,这条边就需要连接
3、重复2步骤,直到连接的边达到n-1条,就结束。最小生成树就形成了
代码
//Kruskal
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int INF=5555555;
struct side{
int s,t;
int len;
}s[55555];
int pre[1100];//并查集用的前驱数组
int n,m;
bool cmp(side a,side b)
{
return a.len<b.len;
}
int find(int x)
{
if(pre[x]==0)
return x;
return pre[x]=find(pre[x]);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(pre,0,sizeof(pre));
for(int i=0;i<m;i++)
{
int s1,t,w;
scanf("%d%d%d",&s1,&t,&w);
s[i].s=s1;
s[i].t=t;
s[i].len=w;
}
sort(s,s+m,cmp);
int sum=0;
int count=0;
for(int i=0;i<m && count<n-1;i++)
{
//记下两端点的队长
int fx=find(s[i].s);
int fy=find(s[i].t);
if(fx!=fy)//不在一个集合
{
pre[fx]=fy;
sum+=s[i].len;
count++;
}
}
printf("%d\n",sum);
}
return 0;
}