Prim

Prim最小生成树算法,以任意节点为根,找出与之相邻的所有便,再将新节点更新并以此节点为根继续进行,dis为已用点到未用点的最短距离。适用于稠密图,时间复杂度O(N^2)。

inline int prim(){
	memset(vis,0,sizeof(vis));
	memset(dis,0x3f,sizeof(dis));
	int cnt=dis[1]=0,x=1,ans=0;/*初始以1为根*/
	for(int i=h[1];i;i=e[i].next){
		int y=e[i].to;
		dis[y]=min(dis[y],e[i].w);
	}
	while(++cnt<n){
		int mi=0x7fffffff;
		vis[x]=1;
		for(int i=1;i<=n;i++)if(!vis[i]&&dis[i]<mi)mi=dis[i],x=i;
		ans+=mi;
		for(int i=h[x];i;i=e[i].next){
			int y=e[i].to;
			dis[y]=min(dis[y],e[i].w);
		}
	}
	if(ans>=0x3f3f3f3f)return false;/*存在点没有被更新过,图不连通,也可以判断存在未访问的节点*/
	return ans;
}

堆优化prim,时间复杂度O((N+M)*log2(N))。

inline int prim(){
	priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	int cnt=dis[1]=0,ans=0;
	q.push({0,1});
	while(!q.empty()&&cnt<n){
		int x=q.top().second,w=q.top().first;
		q.pop();
		if(vis[x])continue;
		cnt++;/*新选入一条边*/
		ans+=w;
		vis[x]=1;
		for(int i=h[x];i;i=e[i].next){
			int y=e[i].to;
			if(dis[y]>e[i].w){/*松弛操作*/
				dis[y]=e[i].w;
				q.push({dis[y],y});/*入队*/
			}
		}
	}
	if(cnt<n)return false;/*图不连通*/
	return ans;
}
posted @ 2022-11-14 17:59  半步蒟蒻  阅读(303)  评论(0)    收藏  举报