最小生成树 ----Prim算法(模板)

PS: B站上的讲解

Prim算法 解决的是最小生成树问题 ,即在给定一个无向图G中求一棵生成树T ,使得这棵树拥有图G 中的所有顶点,且所有边都是来自图G 中的边,并且满足整棵树的边权之和最小。
Prim 算法的基本思想是对图G(V,E) 设置集合S 来存放图G 中已经访问的顶点 ,然后执行n(节点个数) 次下面的两个步骤:

  1. 每次从集合V - S(即未访问过的节点) ,中选择与集合S 最近的一个顶点,记为U,将U 加入集合S ,同时将U 与集合S 相连的边加入最小生成树。
  2. 将节点U 做为接口,优化从U 可以到达的未访问的节点与最小生成树的距离。(类似Dijkstra算法

输入:

6 10
0 1 4
0 4 1
0 5 2
1 2 6
1 5 3
2 3 6
2 5 5
3 4 4
3 5 5
4 5 3

第一行为顶点数和边数
接下来的m行为两个节点以及节点到节点的边权
输出:

15

代码:

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int n,m,vis[100],re = 0,d[100];
//vis为访问标记数组,re为最小生成树的边权之和,d为节点到生成树节点集合的距离。 
struct node{
    
    
	int v,dis;
};
//邻接表读入 
vector<node>e[100];
int prim(int start){
    
    
	//一. 初始化,将起始点与生成树的距离设为0 
	d[start] = 0;
	//二. 循环n(节点个数)次 
	for(int i = 0;i<n;i++){
    
    
		//三. 循环寻找节点,找到距离生成树最近且未访问的点 
		int min = INF ,u = -1;
		for(int j = 0;j<n;j++){
    
    
			if(vis[j] == 0 && d[j] < min){
    
    
				min = d[j];
				u = j;
			}
		} 
		//四. 将节点设为已经访问,且re加上距离 
		vis[u] = 1;
		re += d[u];
		//五. 循环之前找到的距离最小的节点u可以达到的节点 
		for(int k = 0;k<e[u].size();k++){
    
    
			//六. 如果可以改变周围节点到生成树的距离,就优化 
			int v = e[u][k].v;
			if(vis[v] == 0 && e[u][k].dis < d[v]){
    
    
				d[v] = e[u][k].dis; //与Dijkstra算法不同(d[]数组含义不同)
			}
		}
	}
	return re;
}
int main(){
    
    
	//freopen("a.txt","r",stdin);
	//初始节点都未访问 
	memset(vis,0,sizeof vis);  
	//与生成树的距离初始化为无穷大 
	memset(d,INF,sizeof d);
	cin>>n>>m;
	int u,v,k;
	for(int i = 0;i<m;i++){
    
    
		cin>>u>>v>>k;
		node a,b;
		a.v = v;
		a.dis = k;
		b.v = u;
		b.dis = k;
		e[u].push_back(a);
		e[v].push_back(b);
		//若图为无向图记得反向设置。 
	}
	cout<<prim(0);
	return 0;
} 

end.

猜你喜欢

转载自blog.csdn.net/m0_45210226/article/details/106043815