测试地址:The Unique MST
题目大意:给一个连通的无向图,要求判断该图的最小生成树是不是唯一的,如果对于该图的所有除了最小生成树之外的生成树,花费都严格大于最小生成树的花费,则该图的最小生成树是唯一的。如果唯一,输出最小花费,否则输出“Not Unique!”。
做法:用次小生成树的做法来做这一题,如果次小生成树的花费和最小生成树相等,那么最小生成树就不唯一。求次小生成树的方法网上有讲,这里不再赘述。
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define inf 1000000007
using namespace std;
int T,n,m,len[110][110],first[110],last[110],fa[110],mst,smst;
struct edge {int a,b,d,next;} e[50010];
bool used[110];
bool cmp(edge a,edge b)
{
return a.d<b.d;
}
int find(int x)
{
int r=x,i=x,j;
while(r!=fa[r]) r=fa[r];
while(i!=r) j=fa[i],fa[i]=r,i=j;
return r;
}
void merge(int a,int b)
{
int fx=find(a),fy=find(b);
fa[fy]=fx;
}
void kruskal()
{
mst=0;
sort(e+1,e+m+1,cmp);
memset(first,0,sizeof(first));
memset(used,0,sizeof(used));
for(int i=1;i<=n;i++)
{
fa[i]=i;
first[i]=last[i]=m+i;
e[m+i].a=e[m+i].b=i;
e[m+i].next=0;
}
for(int i=1;i<=m;i++)
{
if (find(e[i].a)!=find(e[i].b))
{
for(int j=first[fa[e[i].a]];j;j=e[j].next)
for(int k=first[fa[e[i].b]];k;k=e[k].next)
{
len[e[j].b][e[k].b]=len[e[k].b][e[j].b]=e[i].d;
}
e[last[fa[e[i].a]]].next=first[fa[e[i].b]];
last[fa[e[i].a]]=last[fa[e[i].b]];
merge(e[i].a,e[i].b);
mst+=e[i].d;
used[i]=1;
}
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
memset(first,0,sizeof(first));
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].d);
kruskal();
smst=inf;
for(int i=1;i<=m;i++)
if (!used[i]) smst=min(smst,mst-len[e[i].a][e[i].b]+e[i].d);
if (smst==mst) printf("Not Unique!
");
else printf("%d
",mst);
}
return 0;
}