最小生成树

本文介绍了最小生成树的概念,包括Prim和Kruskal两种基本算法,以及它们的适用场景。 Prim算法从一个点开始逐步添加最近的点,而Kruskal算法按边权重从小到大选择边。此外,文章还提到了拟阵和生成树的性质,并给出了多个例题,如HDU 1233等,帮助理解最小生成树的应用。
摘要由CSDN通过智能技术生成

最小生成树

给定一个无向图,如果它的某个子图中任意两个顶点都互相连通且是一棵树,那么这棵树就是生成树 其中,边权和最小的生成树就是最小生成树(MST)

一些性质
n-1条边

若T1,T2都是最小生成树,则T1,T2的各边权是相同的(可能连接的边不同),换句话说,若边权各不相同,则最小生成树唯一(实际上也是拟阵贪心的性质)

往生成树上加一条边就形成一个环,假设是(u,v)加边,那么就形成(u,…,lca(u,v),…,v,u)这个环

基本算法

Prim

与Dijkstra比较像 Dijkstra是什么(大雾
我们先在某一个集合中搞一个点
定义d[i]表示点i到这个集合的最小距离
然后不断往这个集合里添加离这个集合最近的点,直到所有的点都加入了这个集合。
每一次加入一个点 都要去搞一下这个点的相邻的点 来更新d[i]

感觉一下正确性显然(什么鬼操作
证明 略~~(其实讨厌这个字~~
详见白书106页

int prim()
{
   
	d[0]=0;
	int ans=0;
	while(1)
	{
   
		int u=-1;
		for(int v=0;v<=n;v++)
			if(!vis[v]&&(u==-1||d[v]<d[u]))
				u=v;
		if(u==-1) break;
		vis[u]=1;
		ans+=d[u];
		for(int v=0;v<=n;v++)
			d[v]=min(d[v],c[u][v]);
	}
	return ans;
}

同Dijkstra一样,Prim也可以用堆优化 mark一下
但是我感觉优化效果不明显(可能要在一些特殊数据下或者数据较大的时候吧

Kruskal

按照边的权值从小到大依次check一下,如果不产生环,就把这条边加进去,直到联通所有的点(根据树的性质,则为有n-1条边时
判断是否产生环,主要是看这条边的两个端点是否已经连通
就需要并查集来维护

void Init()
{
   
	for(int i=1;i<=n;i++)
		f[i]=i;
}
int Find(int x)
{
   
	if(f[x]!=x)
		return f[x]=Find(f[x]);
	return f[x];
}
bool Union(int x,int y)
{
   
	int u=Find(x),v=Find(y);
	if(u==v) return 0;
	if(u>v) f[u]=v;
	else f[v]=u;
	return 1;
}
int Kruskal()
{
   
	Init();
	int num=0,ans=0;
	for(int i=1;i<=m;i++)
		if(Union(edge[i].u,edge[i]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值