poj 1679 The Unique MST 次小生成树算法

题目大意是判断一个图的最小生成树是否唯一

求出次小生成树,若次小生成树的权值不等于最小生成树,则唯一,若相等,则不唯一


#include <stdio.h>
#include <string.h>
int map[110][110],max[110][110],p[110],low[110],n,m,vis[110][110];  
 /*max[i][j]表示最小生成树中从i到j的路径中最长的边,map是边,p[i]是prim每次选进去的边一个节点(在之前选进去的集合中的节点)
vis[i][j]若为0,表示i到j无边,等于一表示有边但未选入最小生成树,等于2表示选入了最小生成树*/
int MAX(int a,int b)
{
	if(a>b)
		return a;
	else return b;
}
int prim(int u)
{
	int i,min,v,j,cost=0;
	for(j=1;j<=n;j++)
	{
		low[j]=map[j][u];
		p[j]=u;
	}
	low[u]=-1;
	for(j=1;j<=n-1;j++)
	{
		min=50000;
		for(i=1;i<=n;i++)
		{
			if(low[i]!=-1&&min>low[i])
			{
				min=low[i];
				v=i;
			}
		}	
		low[v]=-1;
		cost+=min;
		vis[v][p[v]]=vis[p[v]][v]=2;/*在生成树中,所以改为2*/
		for(i=1;i<=n;i++)
			if(i!=v)
				max[i][v]=max[v][i]=MAX(min,max[i][p[v]]);/*每次选入一个边都更新一遍max*/
		for(i=1;i<=n;i++)
		{
			if(low[i]!=-1&&map[v][i]<low[i])
			{
				low[i]=map[v][i];
				p[i]=v;
			}
		}
	}
	return cost;
}

int main()
{
	int t,i,j,k,x,y,min,sum,w;
	scanf("%d",&t);
	for(i=0;i<t;i++)
	{
		min=50000;
		scanf("%d%d",&n,&m);
		memset(max,0,sizeof(max));/*刚开始时初始为0*/
		memset(vis,0,sizeof(vis));
		for(j=1;j<=n;j++)
			for(k=1;k<=n;k++)
				map[j][k]=50000;
		for(j=0;j<m;j++)
		{
			scanf("%d%d%d",&x,&y,&w);
			map[x][y]=map[y][x]=w;
			vis[x][y]=vis[y][x]=1;
		}
		sum=prim(1);
		for(j=1;j<=n;j++)
			for(k=1;k<=n;k++)
				if(vis[j][k]==1&&min>sum+map[j][k]-max[j][k])
					/*将不在生成树中的边依次加入生成树,形成一个环,去掉环上原生成树中的最大边形成一棵较大的生成树*/
						min=sum+map[j][k]-max[j][k];
		if(min!=sum)
			printf("%d\n",sum);
		else
			printf("Not Unique!\n");
	}
	return 0;
}


 

你可能感兴趣的:(poj 1679 The Unique MST 次小生成树算法)