poj 1679 The Unique MST(判断最小生成树是否唯一)

题目:http://poj.org/problem?id=1679

思路:

(1) 对图中每条边,扫描其他边,如果存在相同权值的边,则对该边作标记。

(2)求最小生成树。

(3)如果该最小生成树中未包含作了标记的边,则可以判定其唯一;否则,依次去掉这些边再求最小生成树,如果求得的权值和原来的相同,则判定不唯一。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
   int u,v,w;
} t[10005];
int fa[105];
int vis[10005];
int p[100005]; //标记,其他边权值是否跟该边一样
int d[100005]; //是否删除的标记
int flag;   //第一次求最小生成树的标志变量
int n,m;
bool cmp(node a,node b)
{
   return a.w<b.w;
}
int find(int x)
{
   if(x==fa[x])
	   return x;
   return find(fa[x]);
}

void Union(int x,int y)
{
   int a=find(x),b=find(y);
   if(a!=b)
   {  
	  if(a>b)
        fa[b]=a;
	  else
		fa[a]=b;
   }
}
int kruskal()
{
      int i,ans=0,num=0;
	  for(i=0;i<n;i++)
		  fa[i]=i;
	  for(i=0;i<m;i++)
	  {
	      if(d[i]==1)
			  continue;
		  if(find(t[i].u)!=find(t[i].v))
		  {
		       ans+=t[i].w;
			   num++;
			   Union(t[i].u,t[i].v);
			   if(flag)
				   vis[i]=1;
		  }
		  if(num>=n-1)
			  break;
	  }
	  return ans;
}
int main()
{
   int u,v,w,i,j,cas;
   scanf("%d",&cas);
   while(cas--)
   { 
	  scanf("%d%d",&n,&m);
	  for(i=0;i<m;i++)
	  {
         scanf("%d%d%d",&u,&v,&w);
		 t[i].u=u-1,t[i].v=v-1,t[i].w=w;
		 p[i]=0,d[i]=0,vis[i]=0;
	  }
	  for(i=0;i<m;i++)  //标记相同权值的边
	  {
	     for(j=0;j<m;j++)
		 {
		    if(i==j)
				continue;
			if(t[i].w==t[j].w)
				p[i]=1;
		 }
	  }
	  sort(t,t+m,cmp);
	  flag=1;
	  int w1=kruskal(),w2;
	  flag=0;
	  for(j=0;j<m;j++)
	  {
		if(vis[j]&&p[j])
		{
	       d[j]=1;
           w2=kruskal();
		   if(w1==w2)
		   {
		      printf("Not Unique!\n");
			  break;
		   }
		   d[j]=0;
		}
	  }
	  if(j>=m)
		  printf("%d\n",w1);
   }
   return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值