题目链接:http://poj.org/problem?id=1679
1.标记第一次kruskal算法所用到的边。
2.每次只删除其中一条边,用一次kruskal算法,观察结果是否一致,是则不唯一。(记得是只删除其中一条)
3.当所有被标记的边被删过一次后,如果没有一次结果与最开始的一致,则是唯一的。
#include<cstdio>
#include<algorithm>
#include<cstring>
const int N=10010;
using namespace std;
struct node
{
int s,e,dis;
bool used,del,same;
}edge[N];
int parent[110];
int first=1;
bool cmp(const node &a,const node &b){return a.dis<b.dis;}
void Init(){
for(int i=0;i<110;++i)parent[i]=-1;
}
int find(int e)
{
int i,j=e;
while(parent[j]!=-1)j=parent[j];
while(j!=e)
{
i=parent[e];
parent[e]=j;
e=i;
}
return j;
}
int kruskal(int m)
{
int i,x,y,ans=0;
node cur;
for(i=0;i<m;++i)
{
cur=edge[i];
if(cur.del==true) continue;
x=find(cur.s),y=find(cur.e);
if(x!=y){
parent[x]=y;
ans+=cur.dis;
if(first)
edge[i].used=true;
}
}
return ans;
}
void mark_same_edge(int m)
{
for(int i=1;i<m;++i)if(edge[i].dis==edge[i-1].dis){
edge[i-1].same=true;
}
}
int main()
{
int t,n,m,i,w1,w2;
bool tag;
scanf("%d",&t);
while(t--)
{
Init();tag=false;first=true;
memset(edge,0,sizeof(edge));
scanf("%d %d",&n,&m);
for(i=0;i<m;++i)
{
scanf("%d %d %d",&edge[i].s,&edge[i].e,&edge[i].dis);
edge[i].del=false,edge[i].same=false;
}
sort(edge,edge+m,cmp);
w1=kruskal(m);first=false;
mark_same_edge(m);
for(i=0;i<m;++i)
{
if(edge[i].used==true&&edge[i].same==true)
{
Init();
edge[i].del=true;
w2=kruskal(m);
if(w1==w2)
{
puts("Not Unique!");
tag=true;
break;
}
edge[i].del=false;
}
}
if(!tag)
//puts("Unique!");
printf("%d\n",w1);
}
}