首次采用了压行,感觉还不错。
Code:
// luogu-judger-enable-o2
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
void setIO(string a){
freopen((a+".in").c_str(),"r",stdin);
//freopen((a+".out").c_str(),"w",stdout);
}
#define inf 1000000000
#define maxn 300007
int ch[maxn][2],f[maxn],val[maxn],max1[maxn],max2[maxn];
int sta[maxn],tag[maxn];
int lson(int x){ return ch[x][0]; }
int rson(int x){ return ch[x][1]; }
int get(int x){ return ch[f[x]][1]==x; }
int isRoot(int x){ return !(ch[f[x]][0]==x||ch[f[x]][1]==x); }
void mark(int x){ if(x) swap(ch[x][0],ch[x][1]),tag[x]^=1; }
void pushdown(int x){ if(tag[x]) mark(lson(x)), mark(rson(x)), tag[x]=0; }
void pushup(int x){
if(max1[lson(x)]>max1[rson(x)]) max1[x]=max1[lson(x)], max2[x]=max(max2[lson(x)],max1[rson(x)]);
else if(max1[lson(x)]<max1[rson(x)]) max1[x]=max1[rson(x)], max2[x]=max(max2[rson(x)],max1[lson(x)]);
else max1[x]=max1[lson(x)], max2[x]=max(max2[lson(x)],max2[rson(x)]);
if(val[x]>max1[x]) max2[x]=max1[x],max1[x]=val[x];
else if(val[x]!=max1[x]) max2[x]=max(max2[x],val[x]);
}
void rotate(int x) {
int old=f[x],oldf=f[old],which=get(x);
if(!isRoot(old)) ch[oldf][ch[oldf][1]==old]=x;
ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
ch[x][which^1]=old,f[old]=x,f[x]=oldf;
pushup(old),pushup(x);
}
void splay(int x){
int v=0,u=x;
sta[++v]=u;
while(!isRoot(u)) sta[++v]=f[u],u=f[u];
while(v) pushdown(sta[v--]);
u=f[u];
for(int fa;(fa=f[x])!=u;rotate(x))
if(f[fa]!=u) rotate(get(fa)==get(x)?fa:x);
}
void Access(int x){ for(int y=0;x;y=x,x=f[x]) splay(x),ch[x][1]=y,pushup(x); }
void makeRoot(int x){ Access(x),splay(x),mark(x); }
void split(int x,int y){ makeRoot(x),Access(y),splay(y); }
struct Union_Find{
int p[maxn];
int find(int x){ return p[x]==x?x:p[x]=find(p[x]);}
void init(){for(int i=1;i<maxn;++i)p[i]=i;}
void merge(int x,int y){ int a=find(x),b=find(y); if(a!=b) p[a]=b; }
}tree;
struct Edge{
int u,v,c;
Edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}
}edges[maxn];
bool cmp(Edge e1,Edge e2){ return e1.c<e2.c; }
int main(){
//setIO("input");
tree.init();
int n,m,cnt,x,y,ans=inf;
long long sum=0;
scanf("%d%d",&n,&m),cnt=n;
for(int i=1;i<=m;++i) scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].c);
sort(edges+1,edges+1+m,cmp);
for(int i=1;i<=m;++i){
x=edges[i].u,y=edges[i].v;
if(tree.find(x)==tree.find(y)){
split(x,y);
ans=min(ans,edges[i].c-(max1[y]>=edges[i].c?max2[y]:max1[y]));
}
else{
makeRoot(x);
f[f[x]=++cnt]=y;
max1[cnt]=val[cnt]=edges[i].c;
sum+=edges[i].c;
tree.merge(x,y);
}
}
printf("%lld",sum+ans);
return 0;
}