MST一道经典变形题目。问你MST是否唯一。
MST的权是唯一的,但MST不一定唯一。
MST不唯一的必要条件之一是无向网有相同权值的边。
即,MST不唯一,无向网一定有相同权值的边,但是无向网有相同权值的边,MST不一定唯一。
得到一个逆否命题,MST没有使用无向网中相同权值的边,那么MST一定唯一。
如果MST使用了无向图中相同权值的边,那么依次去掉这些边,如果某次去掉之后得到MST的权与最初的MST权是相等的则说明MST不唯一。否则说明唯一。1
标记所有存在相同权值的边。
Kruskal求MST,标记使用过的存在相同权值的边。如果没用使用过相同权值的边,则说明唯一。
否则,依次删除掉被标记的使用过的相同权值的边,如果所得MST与第一次得到的权相等则说明不唯一。
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAXN 105
using namespace std;
struct Edge
{
int a,b,weight;
bool equl,used,dele;
Edge():equl(0),used(0),dele(0) {}
};
Edge e[MAXN*MAXN];
int father[MAXN];
bool fir,uq;
bool cmp(Edge a,Edge b)
{
return a.weight<b.weight;
}
int find(int p)
{
return p==father[p]?p:(father[p]=find(father[p]));
}
void Init(int n)
{
for(int i=0; i<=n; ++i)
father[i]=i;
}
int Kruskal(int n,int m)
{
Init(n);
sort(e,e+m,cmp);
int ans=0;
for(int i=0; i<m; ++i)
{
if(e[i].dele) continue;
int ta=find(e[i].a),tb=find(e[i].b),val=e[i].weight;
if(ta!=tb)
{
father[ta]=tb;
ans+=val;
if(fir&&e[i].equl)
{
e[i].used=true;
uq=false;
}
}
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0; i<m; ++i)
{
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].weight);
e[i].equl=e[i].used=e[i].dele=false;
}
if(m==1)
{
printf("%d\n",e[0].weight);
continue;
}
sort(e,e+m,cmp);
for(int i=1; i<m; ++i)
{
if(e[i].weight==e[i-1].weight)
e[i].equl=e[i-1].equl=true;
}
uq=true;
fir=true;
int ans=Kruskal(n,m);
if(uq)
{
printf("%d\n",ans);
continue;
}
fir=false;
for(int i=0; i<m; ++i)
{
if(!e[i].used) continue;
e[i].dele=true;
int res=Kruskal(n,m);
if(res==ans)
{
uq=false;
break;
}
else uq=true;
e[i].dele=false;
}
if(uq) printf("%d\n",ans);
else puts("Not Unique!");
}
return 0;
}