The Unique MST
Description
Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties:
1. V' = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.
Input
Output
Sample Input
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2
Sample Output
3 Not Unique!
/*
判定MST是否唯一的正确方法:
1、对图中的每条边,扫描其他边,如果存在相同权值的边,则对该边进行标记。
2、然后用Kruskal算法(或prim算法)求MST
3、求得MST后,如果该MST中未包含做了标记的边,即可判定MST唯一;
如果包含作了标记的边,则依次去掉这些边再求MST,如果求得的MST权值和
原MST权值相同,即可判定MST不唯一。
*/
//我是用Kruskal算法求MST的
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int maxn=10000;
struct node
{
int u,v,w; //用于记录边的起始点以及边上的权值大小
int eq,used,del; //eq用于标记是否存在权值相同的边,
//used用于标记在第一次求得的MST中是否包含该边,del用于标记便是否被删除
bool operator <(node a) const
{
return a.w>w;
}
}edge[maxn];
int father[maxn];
int n,m;
bool first;
int find_father(int x)
{
int r;
for(r=x;father[r]>=0;r=father[r]);
while(x!=r)
{
int temp=father[x];
father[x]=r;
x=temp;
}
return r;
}
void unit(int a,int b)
{
int r1=find_father(a),r2=find_father(b);
int temp=father[r1]+father[r2];
if(father[r1]>father[r2])
{father[r1]=r2;father[r2]=temp;}
else
{father[r2]=r1;father[r1]=temp;}
}
int kruskal()
{
int num=0;
int sum=0;
int u,v;
for(int i=0;i<=n;i++)
father[i]=-1;
for(int i=0;i<m;i++)
{
if(edge[i].del==1) continue;//如果边已被删除,则继续下一个
u=edge[i].u,v=edge[i].v;
if(find_father(u)!=find_father(v))
{
num++;
sum+=edge[i].w;
unit(u,v);
if(first) edge[i].used=1;//如果只是第一次求MST,则将用到的边标记为1
}
if(num>=n-1) break;
}
return sum;
}
int main()
{
int t,a,b,c;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
edge[i].u=a,edge[i].v=b,edge[i].w=c;
edge[i].eq=0;edge[i].used=0;edge[i].del=0;
}
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
{
if(i==j) continue;
if(edge[i].w==edge[j].w) edge[j].eq=1; //存在相同的边,标记
}
sort(edge,edge+m);
first=true; //第一次求MST
int w1=kruskal(),w2;
first=false;
int i;
for(i=0;i<m;i++)
{
if(edge[i].used&&edge[i].eq)
{
edge[i].del=1; //用过的存在相同的边的边被删除
w2=kruskal();
if(w1==w2)
{
cout<<"Not Unique!\n";
break;
}
edge[i].del=0;
}
}
if(i>=m) printf("%d\n",w1);
}
return 0;
}