借机复习次小生成树。
对于非树边查询最大边权替换更新答案。
这道题不允许边权相等,那就再维护一个次大值。
咕
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define int long long
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;
ch=getchar();
}return cnt*f;
}
struct node{
int u,v,w,flag;
}edge[300003];
int n,m;
int max1[100003][22],max2[100003][22];int f[100003];int all=0;int fa[100003][22];
int first[100003],nxt[200003],to[200003],w[200003],tot;int dep[100003];
void add(int a,int b,int c){nxt[++tot]=first[a];first[a]=tot;to[tot]=b;w[tot]=c;}
int find(int x){if(x==f[x])return f[x];return f[x]=find(f[x]);}
bool cm(node a,node b){return a.w<b.w;}
void dfs(int u,int faa){
for(int i=1;i<=19;i++){
fa[u][i]=fa[fa[u][i-1]][i-1];
max1[u][i]=max(max1[u][i-1],max1[fa[u][i-1]][i-1]);
max2[u][i]=max(max2[u][i-1],max2[fa[u][i-1]][i-1]);
if(max1[u][i-1]>max1[fa[u][i-1]][i-1]){max2[u][i]=max(max2[u][i],max1[fa[u][i-1]][i-1]);}
else if(max1[u][i-1]<max1[fa[u][i-1]][i-1])max2[u][i]=max(max2[u][i],max1[u][i-1]);
}dep[u]=dep[faa]+1;
for(int i=first[u];i;i=nxt[i]){
int v=to[i];if(v==faa)continue;
max1[v][0]=w[i];max2[v][0]=-0x3f3f3f3f3f3f3f3f;fa[v][0]=u;
dfs(v,u);
}
}
int Lca(int a,int b){
if(dep[a]<dep[b])swap(a,b);
for(int i=19;i>=0;i--){
if(dep[fa[a][i]]>=dep[b])a=fa[a][i];
}
if(a==b)return a;
for(int i=19;i>=0;i--){
if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
}return fa[a][0];
}int sum;int ans=0x3f3f3f3f3f3f3f3f;
int qmax(int x,int y,int maxx){
int gu=-0x3f3f3f3f3f3f3f3f;
for(int i=19;i>=0;i--){
if(dep[fa[x][i]]>=dep[y]){
if(maxx!=max1[x][i])gu=max(gu,max1[x][i]);
else gu=max(gu,max2[x][i]);
x=fa[x][i];
}
}return gu;
}
void query(int x,int y,int key){
int lca=Lca(x,y);//cout<<"before "<<ans<<endl;
ans=min(ans,sum-max(qmax(x,lca,key),qmax(y,lca,key))+key);
//cout<<sum<<" "<<max(qmax(x,lca,key),qmax(y,lca,key))<<" "<<key<<endl;
}
signed main(){
n=in;m=in;
for(int i=1;i<=m;i++){int u=in;int v=in;int w=in;edge[i]={u,v,w,0};}
sort(edge+1,edge+m+1,cm);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++){
int u=edge[i].u,v=edge[i].v;int x=find(u),y=find(v);
if(x!=y){f[x]=y,++all,edge[i].flag=1,sum+=edge[i].w;}
if(all==n-1)break;
}
for(int i=1;i<=m;i++)if(edge[i].flag)
add(edge[i].u,edge[i].v,edge[i].w),add(edge[i].v,edge[i].u,edge[i].w);
max2[1][0]=-0x3f3f3f3f3f3f3f3f;
dfs(1,0);
for(int i=1;i<=m;i++){
if(!edge[i].flag){
int u=edge[i].u,v=edge[i].v;
query(u,v,edge[i].w);
}
}
cout<<ans;
return 0;
}