最小生成树之 prim算法、kruskal算法(详细分析)

最小生成树知识点

什么是最小生成树?

生成树:一个连通图含有图中全部 n n n个顶点,但只有足以构成一棵树的 n − 1 n-1 n1条边。一颗有 n n n个顶点的生成树有且仅有 n − 1 n-1 n1条边,如果生成树中再添加一条边,则必成环。

最小生成树:在连通的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。


如何求到最小生成树?


① Prim算法

原理:从起始顶点出发,选择当前可用的最小权值边,把对应的顶点加入到当前建立的生成树中来。

令初始状态为 w w w,所有顶点的结合为 V V V,当前剩余没用的顶点集合为 v v v
(1) 初始化: u = s , v = V − u u={s},v=V-u u=s,v=Vu
(2) 找出一条连接集合 u u u v v v的最小代价的边 ( u 0 , v 0 ) (u0,v0) (u0,v0),把它连起来,并将 v 0 v0 v0加入到 u u u中,并修改相关权值(集合 u u u v v v的最小代价边)。
(3) 重复操作2,直到所有 n n n个顶点都被连上为止。

最小生成树之 prim算法、kruskal算法(详细分析)_第1张图片
Prim算法过程

代码

代码与最短路中的Dijkstra有点像

#include
#include
#include
using namespace std;
const int M=10005;
int G[M][M];
int dis[M],m,n;
bool flag[M];
int Prim(){
	memset(dis,0x3f,sizeof(dis));
	memset(flag,false,sizeof(flag));
	dis[1]=0;
	int ans=0;
	for(int i=1;i<=n;i++){
		int id=0;
		for(int j=1;j<=n;j++){
			if(!flag[j]&&(id==0||dis[id]>dis[j])){
				id=j;
			}
		}
		flag[id]=true;
		ans+=dis[id];
		for(int j=1;j<=n;j++){
			dis[j]=min(dis[j],G[id][j]);
		}
	}
	return ans;
} 
int main(){
	memset(G,0x3f,sizeof(G));
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		int s,t,w;
		scanf("%d %d %d",&s,&t,&w);
		G[s][t]=G[t][s]=w;
	}
	printf("%d",Prim());
}


② Kruskal算法

原理:从边出发,初始状态下最小生成树选取 0 0 0条边,在计算的过程中,每次添加一条满足条件的最小代价的边进入最小生成树中,直到选取 n − 1 n-1 n1条边为止。

步骤:
(1) 将所有的边按照代价从小到大的顺序进行排序。
(2) 把图中的 n n n个顶点看做是独立的 n n n棵树。
(3) 按照权值从小到大的顺序进行选择,如果连续的两端不属于同一棵树,那么就选取这条线,否则,就不选取并继续查找。
(4) 重复操作3,直到选取了满足条件的 n − 1 n-1 n1条边为止。

最小生成树之 prim算法、kruskal算法(详细分析)_第2张图片

代码

#include
#include
#include
#include
using namespace std;
const int M=100005;
struct edge{
	int u,v,w;
}G[M];
int f[M],n,m;
bool cmp(edge x,edge y){
	return x.w<y.w;
}
int get(int x){
	if(f[x]==x) return x;
	return f[x]=get(f[x]);
}
int Kruskal(){
	sort(G+1,G+1+m,cmp);
	for(int i=1;i<=n;i++){
		f[i]=i;
	}
	int ans=0;
	for(int i=1;i<=m;i++){
		int x=get(G[i].u),y=get(G[i].v);
		if(x==y) continue;
		f[x]=y;
		ans+=G[i].w;
	}
	return ans;
}
int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d %d %d",&G[i].u,&G[i].v,&G[i].w);
	}
	printf("%d",Kruskal());
}

你可能感兴趣的:(最小生成树,算法,c++,图论)