题意:给出n个点,m条边,要你判断最小生成树是否唯一。
思路:先做一次最小生成树操作,标记选择了的边,然后枚举已经被标记了的边,判断剩下的边组成的最小生成树是否与前面的相等,相等,则不唯一,否则唯一......
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int v1,v2;
int dis;
int flg;
} s[10000]; int cmp(const node a,const node b)
{
if(a.dis<b.dis)
return 1;
else
return 0;
} int father[200],n; int kruskal(int num,int m)
{
int ans=0,cnt=1;
for(int i=0; i<m; i++)
{
if(i==num)
continue;
int s1=father[s[i].v1];
int s2=father[s[i].v2];
if(s1!=s2)
{
ans+=s[i].dis;
//s[i].flg=1;
cnt++;
father[s2]=s1;
for(int j=0; j<=n; j++)
if(father[j]==s2)
father[j]=s1;
}
}
if(cnt!=n) return -1;
else return ans;
}
int main()
{
int text;
scanf("%d",&text);
while(text--)
{
int m;
int ans=0;
scanf("%d%d",&n,&m);
for(int i=0; i<=n; i++)
father[i]=i;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&s[i].v1,&s[i].v2,&s[i].dis);
s[i].flg=0;
} sort(s,s+m,cmp);
int cnt=1;
for(int i=0; i<m; i++)
{
int s1=father[s[i].v1];
int s2=father[s[i].v2];
if(s1!=s2)
{
ans+=s[i].dis;
s[i].flg=1;
cnt++;
father[s2]=s1;
for(int j=0; j<=n; j++)
if(father[j]==s2)
father[j]=s1;
}
}
int w=0;
for(int i=0; i<m; i++)
{
if(s[i].flg==0)
continue;
int sum=0;
for(int j=0;j<=n;j++)
father[j]=j;
sum=kruskal(i,m);
//printf("sum==%d\n",sum);
if(sum==ans)
{
w=1;
break;
}
}
if(w==1)
printf("Not Unique!\n");
else
printf("%d\n",ans);
}
return 0;
}