kruskal算法学习笔记(并查集做法)

    kruskal算法是最小生成树的常见算法,与并查集结合使用会更加高效,这篇博文主要介绍并查集做法。

    kruskal算法主要思想如下:读入一个n点m边的图,对于每一条边,用一个结构体存储这条边连接的两个点及其边权。随后根据边权从小到大进行排序。一开始,我们先认为这n个点分属于不同的集合,即每个点自己是一个集合。(并查集初始化:自己的父亲是自己),接着,开始处理已经排好序的m条边。如果当前边的两个点分属于不同的集合,我们就把它们合并,将边权加到最终答案中,并且累加器加一(累加器用来判断当前已加入最小生成树的边数,若其为n-1,则已完成算法,退出循环)。

    由于每次取的都是当前边权最小的边,所以可以保证最后求出的一定是最小生成树。具体过程详见代码:

    

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=2147483647;
struct edge
{
	int u,v,w;
}a[200005];
int f[5005],n,m,ans,sum,k;
int find(int x)
{
	if (f[x]!=x)
	  f[x]=find(f[x]);
	return f[x];
}
bool merge(int t1,int t2)
{
	int r1=find(t1);
	int r2=find(t2);
	if (r1!=r2)
	{  
	  f[r1]=r2;
	  return true;
    }
    return false;
}
bool cmp(edge a,edge b)
{
    return a.w<b.w;
}
int main()
{
	int i,j;
	scanf("%d%d",&n,&m);
	for (i=1;i<=m;i++)
	  scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
	sort(a+1,a+m+1,cmp);
	for (i=1;i<=n;i++)
	  f[i]=i;
	for (i=1;i<=m;i++)
	{
		if (merge(a[i].u,a[i].v))
		{
			sum++;
			ans+=a[i].w;
		}
		if (sum==n-1)
		  break;
	}
	for (i=1;i<=n;i++)
	  if (f[i]==i)
	    k++;
	if (k==1)
	  printf("%d",ans);
	else
	  printf("orz");
	return 0;
}

此为洛谷P3366最小生成树模板题代码。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值