c++最小生成树两种方法:Prim算法 和 Kruskal算法

c++最小生成树两种方法: Prim算法 和 Kruskal算法

    Prim算法: 算法思想: 假设G=(V,E)是连通的,TE是G上最小生成树中边的集合。算法从U={u0}(u0∈V)、TE={}开始。重复执行下列操作: 在所有u∈U,v∈V-U的边(u,v)∈E中找一条权值最小的边(u0,v0)并入集合TE中,同时v0并入U,直到V=U为止。 此时,TE中必有n-1条边,T=(V,TE)为G的最小生成树。 Prim算法的核心:始终保持TE中的边集构成一棵生成树。

算法过程: 随意选取一点 , 寻找最小权值

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f,maxn=100,maxm=maxn*maxn;

struct edge{
          
   
	int from,to,w,nxt;
}e[maxm];

int n,m,head[maxn],cnt,dis[maxn],u,v,w,ans;
bool vis[maxn];

void add(int u,int v,int w){
          
   
	e[++cnt].from=u;
	e[cnt].to=v;
	e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}//链式前向星定义

int main(){
          
   
	cin>>n>>m;
	memset(head,-1,sizeof(head));
	memset(vis,0,sizeof(vis));//集体赋值
	for(int i=0;i<m;i++){
          
   
		cin>>u>>v>>w;
		add(u,v,w);
		add(v,u,w);//无向图两次定义
	}
	memset(dis,inf,sizeof(dis));//未知点赋较大值
	dis[1]=0;//从dis[1]开始寻找
	for(int i=0;i<n;i++){
          
   
		int minw=inf,v;
		for(int x=1;x<=n;x++){
          
   
			if(!vis[x] && dis[x]<=minw){
          
   
				minw=dis[x];
				v=x;
			}
		}
		ans+=minw;
		vis[v]=true;//标点
		for(int k=head[v];k!=-1;k=e[k].nxt){
          
   
			if(e[k].w<dis[e[k].to] && !vis[e[k].to]){
          
   
				dis[e[k].to]=e[k].w;
			}
		}
	}
	cout<<ans;
	return 0;
}

//Prim算法

Kruskal算法: 算法思想: 权重最小生成树问题是指在一棵无向全连接图中找到一个无环子集T,既能将所有的结点连接起来,又具有最小的权重和。

解决问题的核心是每次找到一条安全边加入到边集合A中,使得A仍然是某棵最小生成树的子集。

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define M 100000

int n,m,ans,fa[M];

struct edge{
          
   
	int u,v,w;
}e[M];

bool cmp(edge a,edge b){
          
   
	return a.w < b.w;
}

int getroot(int x){
          
   
	if(x!=fa[x]){
          
   
		fa[x]=getroot(fa[x]);
	}
	return fa[x];
}

int main(){
          
   
	cin>>n>>m;
	for(int i=1;i<=m;i++){
          
   
		cin>>e[i].u>>e[i].v>>e[i].w;
	}
	sort(e+1,e+m+1,cmp);
	for(int i=1;i<=n;i++){
          
   
		fa[i]=i;
	}
	for(int i=1;i<=m;i++){
          
   
		int p=getroot(e[i].u),q=getroot(e[i].v);
		if(p != q){
          
   
			fa[p]=q;
			ans+=e[i].w;
		}
	}
	cout<<ans;
	return 0;
}

//Kruskal算法

戳下方链接 最小生成树模板题

小结: 最小生成树相较于最短路的dijkstra算法和SPFA算法有相似之处,也比最短路容易理解。但要学会这个算法,融会贯通,还需要多下功夫。

经验分享 程序员 微信小程序 职场和发展