C++ P3366 【模板】最小生成树 --- kruskal

版权声明:转载请保留原地址 https://blog.csdn.net/u012972031/article/details/83591454

 Kruskal的用处:

  • 得出一个图的一个最小生成树(最小生成树就是一个图中总权值最小的一个子树)

Kruskal的思想:

  • 由于要获得最小生成树,而最小生成树一定连接了所有结点,所以边权最小的边一定会被选择(这个需要自己证明
  • 然后,我们将边权最小的边进行缩点,缩点的方法是使用并查集,也就是把互相连接的点放到同一个集合。
  • 然后重复第一个步骤。当已选择的边的数量等于点的总数减一时,则最小生成树已创建完成。

Kruskal的具体实现:

  • 获取边权最小的边可以使用sort函数,也可以使用优先队列
  • 缩点可以使用并查集

例题:https://www.luogu.org/problemnew/show/P3366

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int ans=0,cnt=0,n,m,fa[200005];
struct Edge{
	int u,v,w;
}e[200005];
int cmp(Edge a,Edge b){
	return a.w<b.w;
}
void addEdge(int u,int v,int w){
	e[++cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
}
int find(int a){
	while(a!=fa[a]){
		a=fa[a]=fa[fa[a]];
	}
	return a;
}
void kruskal(){
	int eu,ev;
	int sum=0;
	for(int i=1;i<=m;i++){
		eu=find(e[i].u),ev=find(e[i].v);
		if(eu==ev)continue;
		sum++;
		fa[eu]=ev;
		ans+=e[i].w;
		if(sum==n-1)return;
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	for(int i=1;i<=m;i++){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		addEdge(a,b,c);
	}
	sort(e,e+m,cmp);
	kruskal();
	printf("%d\n",ans);
	return 0;
}

欢迎加入我们的OI讨论群

群号:849352599

猜你喜欢

转载自blog.csdn.net/u012972031/article/details/83591454
今日推荐