貌似看起来没几个用kruskal重构树来写该题的
那就直接来一发kruskal重构树的题解
建议学习完kruskal重构树知识点后再来阅读本题解更佳
核心思想在于建完图后,枚举未被选入构成最小生成树的边,利用该边两端点间最小瓶颈路径判断是否需要删除该边
时间复杂度大概是O(Mlog2N)级别的(不太会算只能算个大概QWQ)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
int n,m,fa[maxn*2],p[maxn*2][21],dep[maxn*2];
ll val[maxn*2],ans;
map<int,bool>mp;
struct node{
int u,v;
ll w;
}e[maxn];
bool cmp(node a,node b){
return a.w<b.w;
}
vector<int>G[maxn*2];
void init(){
for(int i=1;i<=2*n;i++)fa[i]=i;
}
int find(int x){
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
void dfs(int u,int f){
dep[u]=dep[f]+1;
p[u][0]=f;
for(int i=1;i<=20;i++)p[u][i]=p[p[u][i-1]][i-1];
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
dfs(v,u);
}
}
int lca(int a,int b){
if(dep[a]>dep[b])swap(a,b);
for(int i=20;i>=0;i--)if(dep[a]<=dep[b]-(1<<i))b=p[b][i];
if(a==b)return a;
for(int i=20;i>=0;i--)
if(p[a][i]!=p[b][i])a=p[a][i],b=p[b][i];
return p[a][0];
}
int main(){
scanf("%d%d",&n,&m);
init();
int cnt=n;
for(int i=1;i<=m;i++)scanf("%d%d%lld",&e[i].u,&e[i].v,&e[i].w);
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++){
int fx=find(e[i].u),fy=find(e[i].v);
if(fx!=fy){
mp[i]=1;
fa[fx]=fa[fy]=++cnt;
G[cnt].push_back(fx);
G[cnt].push_back(fy);
val[cnt]=e[i].w;
}
if(cnt==2*n-1)break;
}
dfs(cnt,0);
for(int i=1;i<=m;i++){
if(mp[i])continue;
if(e[i].w==val[lca(e[i].u,e[i].v)])ans+=e[i].w;
}
cout<<ans;
return 0;
}