首次采用了压行,感觉还不错。
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; }