直接套次小生成树的板子
看一下和最小生成树是不是相同就可以了
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
const int maxn=2e5+10;
const int inf=1e18;
int n,m;
int pre[maxn],deep[maxn],lg[maxn],ok[maxn];
int fa[maxn][21],maxx[maxn][21];
struct p{
int l,r,w;
}a[maxn<<2];
bool com(p a,p b){
return a.w < b.w ;
}
struct edge{
int to,nxt,w;
}d[maxn<<2]; int head[maxn<<2],cnt=1;
void add(int u,int v,int w){d[++cnt] = (edge){v,head[u],w},head[u]=cnt;}
int find(int x){ return x==pre[x]?x:pre[x]=find(pre[x]);}
int kur()
{
sort(a+1,a+1+m,com);
for(int i=1;i<=n;i++) pre[i]=i;
int ans=0;
for(int i=1,j=1;i<n;i++)
for(;j<=m;j++)
{
int fl=find(a[j].l),fr=find(a[j].r),w=a[j].w;
if( fl!=fr )
{
add(a[j].l,a[j].r,w); add(a[j].r,a[j].l,w);
pre[fl]=fr, ans+=w; ok[j]=1;
break;
}
}
return ans;
}
void dfs(int u,int father)
{
deep[u]=deep[father]+1,fa[u][0]=father;
for(int i=1;i<=lg[deep[u]]+1;i++)
{
int r = fa[u][i-1];
fa[u][i]=fa[r][i-1];
maxx[u][i]=max( maxx[u][i-1],maxx[r][i-1] );
}
for(int i=head[u];i;i=d[i].nxt )
{
int v=d[i].to;
if( v==father ) continue;
maxx[v][0]=d[i].w;
dfs(v,u);
}
}
int LCA(int x,int y,int w)
{
int ans = -inf;
if( deep[x]<deep[y] ) swap(x,y);
for(int i=20;i>=0;i--)
if( deep[fa[x][i]]>=deep[y] )
{
ans = max(ans,maxx[x][i] );
x = fa[x][i];
}
if( x==y ) return ans;
for(int i=20;i>=0;i--)
if( fa[x][i]!=fa[y][i] )
{
ans = max(ans,maxx[x][i] );
ans = max(ans,maxx[y][i] );
x=fa[x][i],y=fa[y][i];
}
ans = max(ans,maxx[x][0] );
ans = max(ans,maxx[y][0] );
return ans;
}
void init()
{
cnt=1;
for(int i=1;i<=m;i++) ok[i]=0;
for(int i=0;i<=n;i++) head[i]=0;
for(int i=1;i<=n;i++)
lg[i] = lg[i-1]+((1<<lg[i-1])==i);
}
signed main()
{
int t; cin >> t;
while( t-- )
{
cin >> n >> m;
init();
for(int i=1;i<=m;i++)
cin >> a[i].l >> a[i].r >> a[i].w;
int chu = kur();
dfs(1,0);
int ans = inf;
for(int i=1;i<=m;i++)
{
if( ok[i] ) continue;
int u = a[i].l,v = a[i].r, w = a[i].w;
ans = min( ans,chu-LCA(u,v,w)+w );
}
if( chu!=ans||ans==inf ) cout << chu << endl;
else cout << "Not Unique!\n" ;
}
}