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'.
#include <cstdio>
#include <algorithm>
//经过简单修改,可以变成求次小生成树的代码 ,但是复杂度较高
using namespace std;
const int maxn=105;
const int maxm=10005;
int p[maxn],n,m;
bool is_uni;
struct edge
{
int u,v,w;
bool eql,used,del;
}e[maxm];
inline void init (const int &x) {p[x]=-1;}
int find (int x)
{
return p[x]>=0?p[x]=find(p[x]):x;
}
bool cmp(edge a,edge b)
{
return a.w<b.w;
}
int kruskal ()
{
//printf("MST:\n");
int i,ans=0;
for (i=0 ; i<=n ; ++i)init(i);
sort(e,e+m,cmp);
for (i=0 ; i<m ; ++i)
if(!e[i].del)
{
int s=find(e[i].u),t=find(e[i].v);
if(s!=t)
{
ans+=e[i].w;
int tmp=p[s]+p[t];
p[s]>p[t]?(p[s]=t,p[t]=tmp):(p[t]=s,p[s]=tmp);
if(!is_uni)e[i].used=true;//只标记第一次生成的树的边
//printf("%d %d %d\n",e[i].u,e[i].v,e[i].w);
}
}
//printf("%d\n",ans);
return ans;
}
int main ()
{
int i,j;
int cas,ans,ans2;
scanf("%d",&cas);
while (cas--)
{
scanf("%d%d",&n,&m);
for (i=0 ; i<m ; ++i)
{
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
e[i].eql=e[i].used=e[i].del=false;
}
for (i=0 ; i<m ; ++i)
if(!e[i].eql)
for (j=i+1 ; j<m ; ++j)
if(e[i].w==e[j].w)e[i].eql=e[j].eql=true;
is_uni=false;
ans=kruskal();
is_uni=true;
for (i=0 ; i<m ; ++i)
{
if(e[i].eql==true && e[i].used==true)
{
e[i].del= true;
ans2=kruskal();
if(ans==ans2){is_uni=false;break;}
else e[i].del=false;
}
}
if(is_uni)printf("%d\n",ans);
else printf("Not Unique!\n");
}
return 0;
}