本文主要是介绍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;
}
这篇关于poj 1679 The Unique MST(判断最小生成树是否唯一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!