先简述一下题意:
给定n个点,m条边的无向图,判断最小生成树是否唯一。
我看网上绝大部分人的做法是用求次小生成树的算法做的,想要了解的话可以去看看别的题解,但我认为不用求次小生成树,直接用kruscal的变形就行。
kruscal每次贪心找出最短边,判断是否连接两个不同子集,所以如果最小生成树不唯一一定有两条权值一样的边可以连接同样的两个子集。
所以每次找到一组权值相同的边,两两枚举判断,如果符合上述情况直接输出不唯一。但写起来之后发现比较麻烦,因为每次要把除这两条边的其他权值相同的边先连上再判断,不知道各位大神有没有什么好的做法,希望可以告诉我。
这是我写的最繁琐的代码。。。最好不要看。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define M 10010
using namespace std;
int n,m;
int f[200];
int f2[200];
struct node
{
int x,y,w;
}q[M],p[M];
bool operator < (node a,node b)
{
return a.w<b.w;
}
int find2(int x)
{
if(x!=f2[x])f2[x]=find2(f2[x]);
return f2[x];
}
int find(int x)
{
if(x!=f[x])f[x]=find(f[x]);
return f[x];
}
int main()
{
int tot;
cin>>tot;
for(int tt=1;tt<=tot;tt++)
{
int ans=0;
int a,b,c;
cin>>n>>m;
if(n==1)
{
cout<<"0"<<endl;
continue;
}
for(int i=1;i<=n;i++)
{
f[i]=i;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].w);
}
sort(q+1,q+m+1);
int now=q[1].w;
p[1]=q[1];
int nb=1;
int dis=0;
for(int i1=2;i1<=m;i1++)
{
if(find(q[i1].x)==find(q[i1].y))continue ;
if(dis)break;
if(q[i1].w!=now)
{
now=q[i1].w;
for(int i=1;i<=nb;i++)
{
if(dis)break;
for(int j=i+1;j<=nb;j++)
{
if(dis)break;
for(int i2=1;i2<=n;i2++)
{
f2[i2]=f[i2];
}
for(int i3=1;i3<=nb;i3++)
{
if(i3==i||i3==j)continue;
if(find2(p[i].x)!=find2(p[i].y))
{
f2[find2(p[i3].x)]=find2(p[i3].y);
}
}
if(find2(p[i].x)!=find2(p[i].y))
{
if(find2(p[i].x)==find2(p[j].x)&&find2(p[j].y)==find2(p[i].y))
{
cout<<"Not Unique!"<<endl;
dis=1;
break;
}
if(find2(p[i].x)==find2(p[j].y)&&find2(p[j].x)==find2(p[i].y))
{
cout<<"Not Unique!"<<endl;
dis=1;
break;
}
}
}
}
for(int i=1;i<=nb;i++)
{
if(find(p[i].x)!=find(p[i].y))
{
ans+=p[i].w;
f[find(p[i].x)]=find(p[i].y);
}
}
nb=1;
p[nb]=q[i1];
}
else
{
nb++;
p[nb]=q[i1];
}
}
for(int i=1;i<=nb;i++)
{
if(dis)break;
for(int j=i+1;j<=nb;j++)
{
if(dis)break;
for(int i2=1;i2<=n;i2++)
{
f2[i2]=f[i2];
}
for(int i3=1;i3<=nb;i3++)
{
if(i3==i||i3==j)continue;
if(find2(p[i].x)!=find2(p[i].y))
{
f2[find2(p[i3].x)]=find2(p[i3].y);
}
}
if(find2(p[i].x)!=find2(p[i].y))
{
if(find2(p[i].x)==find2(p[j].x)&&find2(p[j].y)==find2(p[i].y))
{
cout<<"Not Unique!"<<endl;
dis=1;
break;
}
if(find2(p[i].x)==find2(p[j].y)&&find2(p[j].x)==find2(p[i].y))
{
cout<<"Not Unique!"<<endl;
dis=1;
break;
}
}
}
for(int i=1;i<=nb;i++)
{
if(find(p[i].x)!=find(p[i].y))
{
ans+=p[i].w;
f[find(p[i].x)]=find(p[i].y);
}
}
}
for(int i=2;i<=n;i++)
{
if(find(i)!=find(1))
{
cout<<"0"<<endl;
dis=1;
}
}
if(dis==0)
{
cout<<ans<<endl;
}
}
return 0;
}
<pre name="code" class="cpp">