题目: http://poj.org/problem?id=1679
判断 MST是否是唯一的 。
1) 遍历边, 如果权值相同做标记
2)先使用一次 Kruskul / Prim 求 MST 标记使用过的edge
3) 之后 如果edge标记过,即 第一次求MST时记录了, 而且 有相同权值的边,去掉此条边,再次进行Kruskal/prim 如果相同则不唯一,如果所有的都不相同,则唯一
代码
开始WA的时候,怀疑,是否需要判断是否可以 形成生成树,其实没有这种数据的
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define PI acos(-1.0)
#define max(a,b) (a)>(b)? (a):(b)
#define min(a,b) (a)>(b)? (b):(a)
#define INT_MIN -0x7FFFFFFF
#define INT_MAX 0x7FFFFFF
#define M 10005
#define N 105
struct node
{
int u,v,w;
int equ,used,del;
}edge[M];
int n,m;
int first;
int par[N];
int cmp(const void *p1,const void *p2)
{
return (*(struct node *)p1).w - (*(struct node *) p2).w;
}
int find(int x)
{
if(x!=par[x]) par[x]=find(par[x]);
return par[x];
}
int kru()
{
int i,j,k;
int sum=0;
int ma=0;
for(i=0;i<=n;i++)
{
par[i]=i;
}
//first or not ?
for(i=1;i<=m;i++)
{
int a,b;
if(edge[i].del) continue;
a=find(edge[i].u);
b=find(edge[i].v);
if(a!=b)
{
sum++;
par[a]=b;
ma+=edge[i].w;
if(first) edge[i].used=1;
}
if(sum>=n-1) break;
}
return ma;
}
int main()
{
//freopen("in.txt","r",stdin);
int i,j,k;
int t,time=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
edge[i].used=0;
edge[i].del=0;
edge[i].equ=0;
}
for(i=1;i<=m;i++)
{
for(j=1;j<=m;j++)
{
if(edge[i].w==edge[j].w)
{
if(i==j) continue;
edge[i].equ=1;
}
}
}
qsort(edge+1,m,sizeof(edge[0]),cmp);
first=1;
int ans=kru();
//printf("ans : %d \n",ans);
first=0;
for(i=1;i<=m;i++)//开始循环上限,写成了n WA了几发
{
if(edge[i].equ && edge[i].used)
{
edge[i].del=1;
if(ans==kru())
{
printf("Not Unique!\n");break;
}
edge[i].del=0;
}
}
if(i>m) printf("%d\n",ans);
}
return 0;
}