好不容易得到了这个称号,别着急摘下来
--scz
你也可以不用次小生成树做
但是也可以
次小生成树和最小一样大就证明不止一个
次小生成树要是不严格的话,只需要在求出的最小生成树上,加入一条新边,然后生成了一个环,在这个环上呢,删掉最大的边就行了
然后在最小生成树上加一点点东西就够了
存一下任意两点之间的最大的那条边
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int n;
int t,m;
struct b{
int f;
int to;
int v;
}ed[20010];
vector<int> po[110];
//vector是个好东西
int fa[110],maxe[110][110];
int vis[110];
int read(){
int res=0;
int f=1;
char c=getchar();
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
if(c=='-') f=-1,c='0';
while(c>='0'&&c<='9') res=(res<<1)+(res<<3)+c-'0',c=getchar();
return res*f;
}
bool cmp(b x, b y){
return x.v<y.v;
}
int sum;
int Aimee;
int x,y;
int l1,l2;
int find(int x){
return fa[x]==x ? x:fa[x]=find(fa[x]);
}
void kru(){
sum=0;
Aimee=0;
for(int i=1;i<=m;++i){
if(Aimee==n-1)
break;
x=find(ed[i].f);
y=find(ed[i].to);
if(x==y)
continue;
Aimee++;
vis[i]=1;
sum+=ed[i].v;
l1=po[x].size();
l2=po[y].size();
for(int j=0;j<l1;++j){
for(int k=0;k<l2;++k){
maxe[po[x][j]][po[y][k]]=maxe[po[y][k]][po[x][j]]=ed[i].v;
}
}
//因为kr肯定是越往后的边越大
//直接赋值就行
fa[x]=y;
for(int j=0;j<l1;++j)
po[y].push_back(po[x][j]);
//合并两点之间的点
//x还是y无所谓
}
int Ar=0x7f7f7f7f;
for(int i=1;i<=m;++i){
if(!vis[i]){
Ar=min(Ar,sum+ed[i].v-maxe[ed[i].f][ed[i].to]);
}
}
//枚举删边
if(Ar>sum){
cout<<sum<<endl;
}else{
cout<<"Not Unique!"<<endl;
}
}
int main(){
t=read();
while(t--){
n=read();
m=read();
for(int i=1;i<=m;++i){
scanf("%d%d%d",&ed[i].f,&ed[i].to,&ed[i].v);
vis[i]=0;
}
sort(ed+1,ed+m+1,cmp);
for(int i=1;i<=n;++i){
fa[i]=i;
po[i].clear();
po[i].push_back(i);
}
kru();
}
return 0;
}