最小生成树——Kruskal

洛咕博客地址: − > C l i c k H e r e < − ->Click Here<- >ClickHere<,求捧场


万金油 K r u s k a l Kruskal Kruskal

据说 P r i m Prim Prim适用于稠密图?然而好久没写了…… e m m emm emm

算了江一下 K r u s k a l Kruskal Kruskal好了……因为 K r u s k a l Kruskal Kruskal实在是太好理解了……

回顾最小生成树的定义……在一个图中选取若干条边使图连通且边权的和最小

不会的人第一想法肯定是贪心吧……先排个序再瞎搞

K r u s k a l Kruskal Kruskal也就是这样的……不过比纯种贪心多了一些东西……就是并查集,可以用来查询是否连通

这一点很好理解吧,如果两个块已经连通了就不用再选边了

根据上述内容,我们可以写出一个 K r u s k a l Kruskal Kruskal的流程……

1、对所有边按权值从小到大排序

2、遍历每条边

3、判断边两端的块是否连通

4、如果不连通,使答案加上权值,并将两块合并

5、如果连通,跳过

6、重复2~5,直到取的边数到达目标

代码如下

struct Edge
{
	int u,v,dis;
	friend bool operator < (const Edge &x,const Edge &y)
	{
		return x.dis<y.dis;
	}
}t[100005];
int Find(int x)
{
	return x==f[x]?x:f[x]=Find(f[x]);
}
void Merge(int x,int y)
{
	x=Find(x);
	y=Find(y);
	if(x^y) f[x]=y;
}
void Kruskal()
{
	sort(t+1,t+m+1);
	for(int i=1;i<=m;i++)
	{
		int p=Find(t[i].u),q=Find(t[i].v);
		if(p!=q)
		{
			ans+=t[i].dis;
			Merge(p,q);
			num++;
			if(num==n-1) break;
		}
	}
}

你可能感兴趣的:(c++,最小生成树)