https://blog.csdn.net/u013480600/article/details/37968993
#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=100+10;
const int maxm=100*100+10;
struct Edge
{
int u,v,dist;
int id;//原始编号
Edge() {}
Edge(int u,int v,int d,int id):u(u),v(v),dist(d),id(id) {}
bool operator<(const Edge &rhs)const
{
return dist <rhs.dist;
}
};
//结构体1,记录点及权值和编号;
struct Kruskal
{
int n,m;
Edge edges[maxm];
vector<int> E;//保存最小生成树上的边原始序号
int fa[maxn];//并查集相关
int findset(int x)
{
return fa[x]==-1? x: fa[x]=findset(fa[x]);
}
void init(int n)
{
this->n=n;
m=0;
}
void AddEdge(int u,int v,int dist,int id)
{
edges[m++]=Edge(u,v,dist,id);
}
int kruskal(int ID)
{
E.clear();
memset(fa,-1,sizeof(fa));
int sum=0; //最小生成树权值
int cnt=0; //最小生成树边数目
sort(edges,edges+m);
for(int i=0; i<m; i++)
{
if(edges[i].id == ID) continue;//ID边被删除
int u=edges[i].u, v=edges[i].v;
if(findset(u) != findset(v))
{
E.push_back(edges[i].id);
fa[findset(u)] = findset(v);
sum +=edges[i].dist;
if(++cnt>=n-1) break;
}
}
if(cnt<n-1) return -1;
return sum;
}
} KK;
//结构体中进行算法;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
KK.init(n);
for(int i=0; i<m; i++)
{
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
KK.AddEdge(u,v,d,i);
}
int ans1 = KK.kruskal(-1);//就相当于不删除边的情况;
int ans2 = 1e9;
vector<int> E(KK.E); //保存原图最小生成树上的
for(int i=0; i<E.size(); i++)
{
int tmp = KK.kruskal(E[i]);
if(tmp ==-1) continue; //此时图不连通,不存在最小生成树
ans2 = min(ans2,tmp);
if(ans2 == ans1) break;
}
if(ans1==ans2) printf("Not Unique!\n");
else printf("%d\n",ans1);
}
return 0;
}