最小生成树(MST) 的两种经典算法(Prim&&Kruskal)

Prim算法

#include<bits/stdc++.h>
using namespace std;
#define inf 0x7fffffff
int n,m,sum;
int dis[5005],vis[5005];
struct Edge
{
	int des,w;
}ed1,ed2;
vector<Edge>vec[5005];

int prim()
{
	for(int i=2;i<=n;i++)
		dis[i]=inf;//初始化:各点到树的距离为无穷大 
	int now=1;//默认从1开始建树 
	for(int i=0;i<vec[1].size();i++)
		dis[vec[1][i].des]=min(vec[1][i].w,dis[vec[1][i].des]);
	//更新:此时树中有1个元素1,于是各点到树的距离即为到1的距离 
	for(int i=2;i<=n;i++)
	{
		vis[now]=1;
		int minn=inf;
		int index=0;
		for(int j=2;j<=n;j++)
		{
			if(dis[j]<minn&&!vis[j])
			{
				minn=dis[j];
				index=j;
			}
		}//遍历未被访问的各点,找到距离树最近的点 
		if(!index) return -1;//如果各点到树的距离均为无穷大,无法生成MST,返回-1 
		sum+=minn;//加上路径 
		now=index;//新的元素加入树 
		for(int j=0;j<vec[now].size();j++)
		{
			if(vec[now][j].w<dis[vec[now][j].des])
				dis[vec[now][j].des]=vec[now][j].w;
			//遍历新的元素和其余各点的距离,更新各点到树的最小距离 
		}
	}
	return sum;
}

int main()
{
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int a,b,len;
		scanf("%d%d%d",&a,&b,&len);
		ed1.des=a,ed2.des=b,ed1.w=ed2.w=len;
		vec[a].push_back(ed2);
		vec[b].push_back(ed1);
	}
	int ans=prim();
	if(ans==-1) cout<<"There is no minimum spanning tree";
	else cout<<ans;
	return 0;
} 

Kruskal算法

#include<bits/stdc++.h>
using namespace std;
int n,e,i;
int F[1501];
struct Edge
{
	int from;
	int to;
	int w;
}edge[1501];
bool cmp(Edge x,Edge y)
{
	return x.w<y.w;
}
int find(int x)
{
	if(F[x]==x) return F[x];
	else return F[x]=find(F[x]);
}
bool fun(int a,int b)
{
	int x=find(a);
	int y=find(b);
	if(x!=y)
	{
		F[y]=x;
		return true;
	}
	return false;
}

int main()
{
	scanf("%d%d",&n,&e)
	int total=0,cnt=0;
	for(i=0;i<e;i++)
		scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].w);
	for(i=0;i<n;i++)	F[i]=i;
	sort(edge,edge+e,cmp);
	for(i=0;i<e;i++)
	{
		if(fun(edge[i].from,edge[i].to))
		{
			total+=edge[i].w;
			cnt++;
		}
		if(cnt==n-1) break;
	}
	if(cnt==n-1) printf("%d\n",total);
    else cout<<"There is no minimum spanning tree."<<endl;
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春弦_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值