bzoj3669: [Noi2014]魔法森林
LCT.
将边按a从小到大排序后不断往进加,出现环就把b最大的边去除掉。
lct中边也要单独建一个节点保存边权。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 200000 + 10; const int maxm = 800000 + 10; const int inf = 0x7f7f7f7f; struct BCJ { int f[maxn]; int find(int x) { return f[x]==x?x:f[x]=find(f[x]); } void combine(int u,int v) { int ru=find(u),rv=find(v); f[rv]=ru; } int query(int u,int v) { int ru=find(u),rv=find(v); return ru==rv; } BCJ() {for(int i=1;i<maxn;i++) f[i]=i;} }bcj; struct LCT { int l[maxn],r[maxn],f[maxn]; int mb[maxn],b[maxn],stack[maxn],sp; bool root[maxn],rev[maxn]; void reverse(int x) { rev[x]^=1; } void push(int x) { if(rev[x]) { swap(l[x],r[x]); rev[l[x]]^=1; rev[r[x]]^=1; rev[x]=0; } } void push_route(int x) { sp=0; while(!root[x]) { stack[++sp]=x; x=f[x]; } stack[++sp]=x; for(int i=sp;i>=1;i--) push(stack[i]); } void update(int x) { mb[x]=x; if(b[mb[l[x]]]>b[mb[x]]) mb[x]=mb[l[x]]; if(b[mb[r[x]]]>b[mb[x]]) mb[x]=mb[r[x]]; } void lr(int x) { int y=f[x]; r[y]=l[x]; if(l[x]) f[l[x]]=y; f[x]=f[y]; if(root[y]) {root[x]=1; root[y]=0;} else if(l[f[y]]==y) l[f[y]]=x; else r[f[y]]=x; f[y]=x; l[x]=y; update(y); update(x); } void rr(int x) { int y=f[x]; l[y]=r[x]; if(r[x]) f[r[x]]=y; f[x]=f[y]; if(root[y]) {root[x]=1; root[y]=0;} else if(l[f[y]]==y) l[f[y]]=x; else r[f[y]]=x; f[y]=x; r[x]=y; update(y); update(x); } void rotate(int x) { if(l[f[x]]==x) rr(x); else lr(x); } void splay(int x) { push_route(x); while(!root[x]) { if(root[f[x]]) rotate(x); else if((l[f[x]]==x)==(l[f[f[x]]]==f[x])) {rotate(f[x]); rotate(x);} else {rotate(x); rotate(x);} } } void access(int x) { for(int y=0;x;x=f[y=x]) { splay(x); root[r[x]]=1; root[r[x]=y]=0; update(x); } } void cut(int x,int y) { access(x); splay(x); reverse(x); access(y); splay(y); f[x]=l[y]=0; root[x]=1; } void link(int x,int y) { access(x); splay(x); reverse(x); f[x]=y; } int query(int x,int y) { access(x); splay(x); reverse(x); access(y); splay(y); return mb[y]; } int& operator [] (int x) { return b[x]; } LCT() { for(int i=0;i<maxn;i++) { root[i]=1; b[i]=-inf; mb[i]=i; } } }lct; struct Edge { int u,v,a,b; void init() { scanf("%d%d%d%d",&u,&v,&a,&b); } }e[maxm]; bool cmp(Edge a,Edge b) { return a.a<b.a || (a.a==b.a && a.b<b.b); } int n,m,res=inf; int main() { //freopen("ex_forest3.out","w",stdout); //freopen("ex_forest3.in","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) e[i].init(); sort(e+1,e+m+1,cmp); for(int i=1,bq;i<=m;i++) { if(bcj.query(e[i].u,e[i].v)) { bq=lct.query(e[i].u,e[i].v); if(lct[bq]>e[i].b) { lct.cut(e[bq-n].u,bq); lct.cut(e[bq-n].v,bq); lct[i+n]=e[i].b; lct.link(e[i].u,i+n); lct.link(e[i].v,i+n); } } else { bcj.combine(e[i].u,e[i].v); lct[i+n]=e[i].b; lct.link(e[i].u,i+n); lct.link(e[i].v,i+n); } if(bcj.query(1,n)) { res=min(res,lct[lct.query(1,n)]+e[i].a); } } printf("%d\n",res<inf?res:-1); return 0; }