最小生成树两种常用算法

3 篇文章 0 订阅
2 篇文章 0 订阅

最小生成树的简易实现

一:Kruskal 算法
①算法核心思想:
Kruskal是实现最小生成树比较简单的一种算法。该算法主要是应用了并查集的思想,先对图各边进行按权值从小到大排序,再孤立各个点,然后按序遍历各边将在集合外的点并到集合里,形成一个最小生成树复杂度最少为O(nlogn)。
②例题P2504聪明的猴子
AC代码:

#include<bits/stdc++.h>
using namespace std;
struct node{
	int x,y;
	int len;
}w[1000009];
int pre[1000009];
int bloon[1000009];
int wood[1000009][3];

int find(int x){
	if(x==pre[x]){
		return x;
	}
	return pre[x]=find(pre[x]);//路径压缩算法
}

int cmp(node a,node b){
	return a.len<b.len;
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>bloon[i];
	}
	int m;
	cin>>m;
	for(int i=1;i<=m;++i){
		cin>>wood[i][1]>>wood[i][2];
	}
	int k=0;	
	for(int i=1;i<=m;++i){
		for(int j=1;j<=m;++j){
			if(i!=j){
				w[++k].x=i;
				w[k].y=j;
				w[k].len=sqrt((wood[i][1]-wood[j][1])*(wood[i][1]-wood[j][1])+(wood[i][2]-wood[j][2])*(wood[i][2]-wood[j][2]));
			}
		}
	}	
	for(int i=1;i<=m;++i){
		pre[i]=i;//孤立各点
	}	
	sort(w+1,w+k+1,cmp);//自定义一个cmp排序函数	
	int length;
	int cnt=m;
	for(int i=1;i<=k;++i){
		if(cnt==1)break;
		int s1=find(w[i].x);int s2=find(w[i].y);
		if(s1!=s2){
			cnt--;
			pre[s1]=s2;
			length=w[i].len;
		}
	}
	int ans=0;
	for(int i=1;i<=n;++i){
		if(bloon[i]>=length)ans++;
	}
	cout<<ans<<endl;
	return 0;
}

二:Prim算法
①算法核心思想:
个人认为Prim算法会对初学者更友好一点,因为它是直接并和各点。首先把各点的距离设为无限大,把各点标记为零,然后遍历各点,找到与标记为一的点距离最近的点,然后更新该点标记为一,把其他“零点”到“一点”的距离更新为最短距离,算法复杂度O(n^2+m)。
②例题#2419繁忙的都市
AC代码:

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;

int st[1009][1009];

int main()
{
	int n,m;
	cin>>m>>n;
	int x,y;
	for(int i=1;i<=n;++i){
		cin>>x>>y;
		cin>>st[x][y];
		st[y][x]=st[x][y];
	}
	int p[1009]={0};
	int v[1009];
	memset(v,0x7f,sizeof(v));
	v[1]=0;
	int maxv=0;
	for(int i=1;i<=m;++i){
		int k=0;
		int j;
		for(j=1;j<=m;++j){
			if(!p[j]&&v[k]>v[j])k=j;
		}
		p[k]=1;
		maxv=max(maxv,v[k]);
		for(j=1;j<=m;++j){
			if(!p[j]&&st[j][k]<v[j]&&st[j][k]!=0)v[j]=st[j][k];
		}		
	}
	cout<<m-1<<" "<<maxv<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

某六十九岁合法萝莉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值