0
点赞
收藏
分享

微信扫一扫

算法学习:Prim算法解决最小生成树

有点d伤 2022-01-13 阅读 76

Prim算法

思想:

prim算法对图G(V,E)设置集合S,存放已被放访问的顶点,然后对每次从V-S中选择与集合S的最短距离最小的顶点(为u),访问并加入集合S。之后,令顶点u为中介点,优化所有从u能到达的顶点v与集合S之间的最短距离。这样执行n次,直到集合S已包含所有顶点。

具体实现:

prim算法需要实现两个关键的概念,即集合S的实现、顶点Vi(0≤i≤n-1)与集合S的最短距离

集合S的实现方法:

用一个bool型数组vis[]表示顶点是否已被访问。其中vis[i]==true表示顶点Vi未被访问

顶点与集合S的最短距离:

令int型数组d[]来存放顶点Vi(0≤i≤n-1)与集合S的最短距离。初始时除了起点s的d[s]赋为0,其余顶点都赋为一个很大的数来表示inf,即不可达。

以下是核心代码思想:

const int maxv=1000;//最大顶点数
const int inf=100000000;//设inf为一个很大的数
struct node{
	int v,dis; //v为边的目标顶点,dis为边权 
}; 
vector<node> adj[maxv];//图G,adj存放从顶点u出发可以到达的所有顶点
int n;//n为顶点数
int d[maxv];//顶点与集合S的最短距离 
bool vis[maxv]={false};//标记数组,vis[i]==true表示已访问
intprim(){//默认0号为初始点,函数返回最小生成树的边权之和 
	fill(d,d+maxv,inf);//fill函数将整个d数组赋为inf
	d[0]=0;//只有0号顶点到集合s的距离为0,其余为inf 
	 int ans=0;//存放最小生成树边权之和 
	 for(int i=0;i<n;i++){//循环n次 
	 	int u=-1,min=inf;//u为到最小点的编号,min存放该最小点的边权 
		for(int j=0;j<n;j++){
			if(vis[j]==false&&d[j]<min){//找到未访问的顶点中d[]最小的 
				u=j;
				min=d[j];
			}
		}
		//找不到小于inf的d[u],则剩下的顶点和集合S不连通
		if(u==-1)return -1;
		vis[u]=true;//标记u为已访问
		ans+=d[u];//将与集合S距离最小的边加入最小生成树
		for(int j=0;j<adj[u].size();j++){
			int v=adj[u][j].v;//通过邻接表直接获得u能到达的顶点v
			if(vis[v]==false&&adj[u][j].dis<d[v]){
				//如果v未访问&&以u未中介点可以使v离集合s更近
				d[v]=adj[u][v].dis;//将g[u][v]赋值给d[v] 
			} 
		}
	 }
	 return ans;//返回最小生成树的边权之和 
} 
举报

相关推荐

0 条评论