您的位置:首页 > 产品设计 > UI/UE

Poj-1679 The Unique MST -最小生成树

2013-06-10 16:44 441 查看
求最小生成树是否唯一;

题中共有100个顶点,则边最多有100*99条,开始因为数组开小了,一直WA!最少生成树不唯一则图中一定有权值相同的边,则只需首先求一次MST,然后依次删除权值重复且在第一次求MST中用过的边!若再求出来的MST与第一次的权值相同,则说明最小生成树不唯一!

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 10010
typedef struct node
{
int u,v,w,rep,used,del;     //多增加三个记录信息,一次是:是否有与其相同的权值的边,第一次构造MST时是否被使用,删除标记。
}node;
node map[MAX];
int parent[MAX];
int n,m,ans;
int cmp(const void *a,const void *b)
{
node *aa=(node *)a;
node *bb=(node *)b;
return aa->w - bb->w;
}
void UFset()
{
int i;
for (i=1;i<=n;i++)
{
parent[i]=-1;
}
}
int find(int x)
{
int s;
for (s=x;parent[s]>0;s=parent[s]);
while (s!=x)
{
int temp=parent[x];
parent[x]=s;
x=temp;
}
return s;
}
void unio(int x1,int x2)
{
int x=find(x1);
int y=find(x2);
if (parent[x]<parent[y])
{
parent[x]+=parent[y];
parent[y]=x;
}
else
{
parent[y]+=parent[x];
parent[x]=y;
}
}
int kruskal()
{
UFset();
int i,j,k;
int sum=0,max=0;
for (i=0;i<m;i++)
{
if  (map[i].del)
continue;
int u=map[i].u;
int v=map[i].v;
if (find(u)!=find(v))
{
unio(u,v);
max+=map[i].w;
if (ans) //如果是第一次构造MST则标记边是否被使用
map[i].used=1;
sum++;
}
if (sum==n-1)
break;
}
return max;
}
int main()
{
int t;
while (scanf("%d",&t)!=EOF)
{
while (t--)
{
int i,j,w1,w2;
int flag=1;
ans=1;
scanf("%d%d",&n,&m);
for (i=0;i<m;i++)
{
scanf("%d%d%d",&map[i].u,&map[i].v,&map[i].w);
map[i].del=map[i].used=map[i].rep=0;
for (j=0;j<i;j++)
{
if (map[j].w==map[i].w) //判断是否有与其权值重复的边
{
map[j].rep=1;
map[i].rep=1;
}
}
}
qsort(map,m,sizeof(node),cmp);
w1=kruskal(); //第一次构造出来的MST的权值
ans=0;
for (i=0;i<m;i++)
{
if (map[i].used&&map[i].rep) //如果这条边在第一次构造MST时被使用,且有与其权值重复的边,则删去再求一次MST。
{
map[i].del=1;
w2=kruskal();
map[i].del=0;
if (w1==w2)        //如果有相同的权值的则MST不唯一,跳出不用继续判断了。
{
flag=0;
break;
}
}
}
if (flag)
printf("%d\n",w1);
else
printf("Not Unique!\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息