【POJ1679】The Unique MST-次小生成树(判断最小生成树唯一性)

测试地址:The Unique MST

题目大意:给一个连通的无向图,要求判断该图的最小生成树是不是唯一的,如果对于该图的所有除了最小生成树之外的生成树,花费都严格大于最小生成树的花费,则该图的最小生成树是唯一的。如果唯一,输出最小花费,否则输出“Not Unique!”。

做法:用次小生成树的做法来做这一题,如果次小生成树的花费和最小生成树相等,那么最小生成树就不唯一。求次小生成树的方法网上有讲,这里不再赘述。

以下是本人代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define inf 1000000007
using namespace std;
int T,n,m,len[110][110],first[110],last[110],fa[110],mst,smst;
struct edge {int a,b,d,next;} e[50010];
bool used[110];

bool cmp(edge a,edge b)
{
  return a.d<b.d;
}

int find(int x)
{
  int r=x,i=x,j;
  while(r!=fa[r]) r=fa[r];
  while(i!=r) j=fa[i],fa[i]=r,i=j;
  return r;
}

void merge(int a,int b)
{
  int fx=find(a),fy=find(b);
  fa[fy]=fx;
}

void kruskal()
{
  mst=0;
  sort(e+1,e+m+1,cmp);
  memset(first,0,sizeof(first));
  memset(used,0,sizeof(used));
  for(int i=1;i<=n;i++)
  {
    fa[i]=i;
	first[i]=last[i]=m+i;
	e[m+i].a=e[m+i].b=i;
	e[m+i].next=0;
  }
  
  for(int i=1;i<=m;i++)
  {
    if (find(e[i].a)!=find(e[i].b))
	{
	  for(int j=first[fa[e[i].a]];j;j=e[j].next)
	    for(int k=first[fa[e[i].b]];k;k=e[k].next)
		{
		  len[e[j].b][e[k].b]=len[e[k].b][e[j].b]=e[i].d;
		}
	  e[last[fa[e[i].a]]].next=first[fa[e[i].b]];
	  last[fa[e[i].a]]=last[fa[e[i].b]];
	  merge(e[i].a,e[i].b);
	  mst+=e[i].d;
	  used[i]=1;
	}
  }
}

int main()
{
  scanf("%d",&T);
  while(T--)
  {
    scanf("%d%d",&n,&m);
	memset(first,0,sizeof(first));
	for(int i=1;i<=m;i++)
	  scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].d);
	
	kruskal();
	
	smst=inf;
	for(int i=1;i<=m;i++)
	  if (!used[i]) smst=min(smst,mst-len[e[i].a][e[i].b]+e[i].d);
	if (smst==mst) printf("Not Unique!\n");
	else printf("%d\n",mst);
  }
  
  return 0;
}


posted @ 2017-03-19 10:49  Maxwei_wzj  阅读(112)  评论(0编辑  收藏  举报