最小生成树(Kruskal算法)

本文详细介绍了使用Kruskal算法解决最小生成树问题的方法。通过排序边权值并利用并查集判断环路,实现从连通图中寻找包含所有顶点的极小子图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念

一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边

模板题

在这里插入图片描述
在这里插入图片描述

Kruskal算法

先把边按照权值进行排序,用贪心的思想优先选取权值较小的边,并依次连接,若出现环则跳过此边(用并查集来判断是否存在环)继续搜,直到已经使用的边的数量比总点数少一即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
long long n,m;
struct node{
	int start,end,v;
};
node edge[2000005];
int parent[5005],rank[5005];
//并查集路径压缩 
int find(int x){
	if(x==parent[x])return x;
	return parent[x]=find(parent[x]);
}
//秩优化 
void unio(int x,int y){
	int x_root=find(x);
	int y_root=find(y);
	if(x_root==y_root)return;
	if(rank[x_root]>rank[y_root]){
		parent[y_root]=x_root;
	}else{
		parent[x_root]=y_root;
		if(rank[x_root]==rank[y_root]){
			rank[y_root]++;
		}
	}
}
bool cmp(node a,node b){
	return a.v<b.v;
}
int main(){
	scanf("%lld%lld",&n,&m);
	//初始化并查集 
	for(int i=0;i<=n;i++){
		parent[i]=i;
		rank[i]=0;
	}
	for(int i=0;i<m;i++){
		scanf("%d %d %d",&edge[i].start,&edge[i].end,&edge[i].v);
	}
	//排序 
	sort(edge,edge+m,cmp);
	long long ans=0,con=0;
	//扫描边 
	for(int i=0;i<m;i++){
		//把祖宗都提前求出来减少复杂度 
		int eu=find(edge[i].start); 
		int ev=find(edge[i].end);
		if(eu!=ev){//不在同一个集合 
			ans+=edge[i].v;
			unio(eu,ev);//加入集合 
			con++;
			if(con==n-1)break;//n个顶点的最小生成树有n-1条边 
		}
	}
	if(con<n-1){
		cout<<"orz"<<endl;
	}else{
		printf("%lld\n",ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值