Title

数据结构-造树计划-最小生成树

最小生成树

思路

  • 沿某一点绕一圈,遇到最小的点往路径最小的点走

  • 并用p[]数组来记录该点的父结点

    p[v]=u(表示v的父节点是u),方便求出路径和sum+=G[i][p[i]]

  • 如果说p[v]=提前设定好的值,也就是说它没有被改变,那么要么这个点是出发点,要么这个点是被“隔离”的。

  • 加强理解的手段,用color数组,取三个值分别表示已经被用(BLACK),要被用(GRAY)和还没有探索到(WHITE)

  • 确定新起点(注意原起点打通了与新起点的通道(使得这些点变成了灰色(缓冲点)),d[v]=d[u][v]

  • 注意:可能还要考虑重边和自环

AC代码P3366 【模板】最小生成树

#include<iostream>
#include<stdio.h>
using namespace std;
static const int MAX=5005;
static const int WHITE=0;//表示未用过的点 
static const int GREY=1;//表示待用的点 
static const int BLACK=2;//表示用过的点 
static const int INFTY=999999;
int G[MAX][MAX];
int p[MAX];
int color[MAX];
int d[MAX];
int num,n;
void prim()
{
	//初始化
	for(int i=1;i<=num;i++)
	{
		p[i]=-1;
	    color[i]=WHITE;	
	    d[i]=INFTY; 
	} 
	
	d[1]=0;
	
	
	while(1)
	{
		int u=-1;
		int minv=INFTY;
		
	//	cout<<2<<endl;
		for(int i=1;i<=num;i++)
		{	
		  //  cout<<3<<endl;
			if(d[i]<minv&&color[i]!=BLACK)
			{
	//			cout<<4<<endl;
				
				u=i;
	//			cout<<u<<endl;
				minv=d[i];
			}
		}
		
		if(u==-1)break;
		
		color[u]=BLACK;
		
		for(int v=1;v<=num;v++)
		{
			if(color[v]!=BLACK&&d[v]>G[u][v]&&u!=v)
			{
				color[v]=GREY;
				d[v]=G[u][v];
				p[v]=u;
			}
		}
	}
	
	int total=0;
	int flag=1; 
	for(int v=2;v<=num;v++)
	{
	//	cout<<6<<endl;
		if(p[v]==-1)
		{
			flag=0;
			cout<<"orz";
			break;
		}
		total+=G[v][p[v]];
	//	cout<<p[v]<<"     "<<G[v][p[v]]<<"     "<<total<<endl;
	}
	if(flag)cout<<total;
}
int main()
{
	cin>>num>>n;
	
	for(int i=1;i<=num;i++)
	{
		for(int j=1;j<=num;j++)
		{
			G[i][j]=INFTY;
			G[j][i]=INFTY;
		}
	}
	
	for(int i=1;i<=n;i++)
	{
		int s,t,e;
		cin>>s>>t>>e;
		if(G[s][t]>=e)
		{
		G[s][t]=e;
		G[t][s]=e;
		}
		//cout<<G[s][t];
	}
	prim();
	
	return 0;
}

其他

距离无穷大

static const int INFTY =(1<<21);

参考资料

  1. 挑战程序设计竞赛

  2. zjl大佬

  3. 洛谷链接

posted @ 2021-03-14 12:49  BeautifulWater  阅读(73)  评论(0编辑  收藏  举报