Prim算法

Prim算法是由R.C.Prim于1956年提出,是一种构造性算法。假设G=(V,E)是一个具有n个顶点的带权无向连通图,T=(U,TE)是G的最小生成树,其中,U是T的顶点集,TE是T的边集,则由G构造从起始顶点v出发的最小生成树T的步骤如下:

  1. 初始化U={v},以v到其他顶点的所有边为候选边;
  2. 从候选边中挑选出权值最小的边加入TE,设该边在V-U中顶点为k,将k加入U中;
  3. 考察当前V-U中所有的顶点j,修改候选边,如果(k,j)的权值小于原来和顶点j关联的候选边,则用(k,j)取代后者作为候选边;
  4. 重复2~3两步n-1次,就能得到最小生成树T;

Prim算法过程图解:

v表示顶点,dist存放候选边,标记为红色表示属于最小生成树中的顶点和边:

(1)选0作为初始顶点添加到最小生成树的点集中,以0到其他顶点的边作为候选边,dist[v]=∞表示当前不存在到顶点v的边;

(2)从候选边中选出权值最小为1的边添加到最小生成树的边集中,以该边所对应的顶点2到其顶点的边更新数组dist,顶点2添加到最小生成树的点集中;

(3)从候选边中选出权值最小为4的边添加到最小生成树的边集中,以该边所对应的顶点5到其顶点的边更新数组dist,顶点5添加到最小生成树的点集中;

(4)从候选边中选出权值最小为2的边添加到最小生成树的边集中,以该边所对应的顶点3到其顶点的边更新数组dist,顶点3添加到最小生成树的点集中;

(5)从候选边中选出权值最小为5的边添加到最小生成树的边集中,以该边所对应的顶点1到其顶点的边更新数组dist,顶点1添加到最小生成树的点集中;

(6)从候选边中选出权值最小为3的边添加到最小生成树的边集中,以该边所对应的顶点4到其顶点的边更新数组dist,顶点4添加到最小生成树的点集中;

至此就得到一颗最小生成树;

模板函数:

const int Maxsize = 105;
const int Inf=0x3f3f3f3f;
int map[Maxsize][Maxsize];//邻接矩阵存图 
int dist[Maxsize];        //最小生成树的候选边集 
bool vis[Maxsize]={0};    //1表示最小生成树的点 
int n;
int prim(int v)//初始顶点v 
{
	int ans=0;                      //最小生成树上所有边的权值和 
	for(int i=0;i<n;i++)            //通过初始顶点v到其他顶点的边更新候选边集dist 
		dist[i]=map[v][i];
	vis[v]=1;                       //标记为1,表示添加到最小生成树的点集中 
	while(1)                        //最多n-1次 
	{
		int Min=Inf;                //存放候选边最小权值,初始化为最大 
		v=-1;                       //存放最小权值候选边所对应的顶点 
		for(int i=0;i<n;i++)        //遍历候选边集 
		{
			if(!vis[i]&&dist[i]<Min)//如果顶点i不在最小生成树点集中,且到i的候选边权值小于Min 
			{
				Min=dist[i];        //更新最小权值 
				v=i;                //更新小权值候选边所对应的顶点 
			}
		}
		if(v==-1)                   //没找到符合条件的顶点就结束循环 
			break;
		vis[v]=1;                   //将顶点v添加到最小生成树的点集中 
		ans+=dist[v];               //累加最小生成树上的边权值 
		for(int i=0;i<n;i++)        //通过v到其他顶点的边更新候选边集dist 
			if(!vis[i]&&map[v][i]<dist[i])//顶点i没被标记,且(v,i)的权值小于dist[i] 
				dist[i]=map[v][i];  //更新候选边集 
	}
	return ans;                     //放回最小生成树的权值和 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值