luogu 2173 [ZJOI2012]网络 LCT
建10棵动态树就完事了~
#include <bits/stdc++.h> #define N 100004 #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) using namespace std; int A[N]; map<int,int>pp[N],lk[N]; struct Link_Cut_Tree { #define lson t[x].ch[0] #define rson t[x].ch[1] int sta[N]; struct Node { int ch[2],f,max,val,rev,son; }t[N]; int isrt(int x) { return !(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x); } int get(int x) { return t[t[x].f].ch[1]==x; } void pushup(int x) { if(!x) return; t[x].max=t[x].val; if(lson) t[x].max=max(t[x].max, t[lson].max); if(rson) t[x].max=max(t[x].max, t[rson].max); } void mark(int x) { if(x) t[x].rev^=1,swap(lson,rson); } void pushdown(int x) { if(x&&t[x].rev) { t[x].rev=0; if(lson) mark(lson); if(rson) mark(rson); } } void rotate(int x) { int old=t[x].f,fold=t[old].f,which=get(x); if(!isrt(old)) t[fold].ch[t[fold].ch[1]==old]=x; t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old; t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold; pushup(old),pushup(x); } void splay(int x) { int v=0,u=x,fa; for(sta[++v]=u;!isrt(u);u=t[u].f) sta[++v]=t[u].f; for(;v;--v) pushdown(sta[v]); for(u=t[u].f;(fa=t[x].f)!=u;rotate(x)) if(t[fa].f!=u) rotate(get(fa)==get(x)?fa:x); } void Access(int x) { for(int y=0;x;y=x,x=t[x].f) { splay(x); if(rson) t[x].son++; if(y) t[x].son--; rson=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); } void link(int x,int y) { makeroot(x),makeroot(y),t[x].f=y,t[y].son++; } void cut(int x,int y) { makeroot(x),Access(y),splay(y); t[y].ch[0]=t[x].f=0; pushup(y); } int find(int x) { Access(x),splay(x); for(pushdown(x);lson;pushdown(x)) x=lson; return x; } int check(int x) { makeroot(x); if(t[x].son==0) return 1; if(t[x].son==1 && !rson) return 1; return 0; } #undef lson #undef rson }op[10]; int main() { // setIO("input"); int n,m,C,K,i,j; scanf("%d%d%d%d",&n,&m,&C,&K); for(i=1;i<=n;++i) { scanf("%d",&A[i]); for(j=0;j<C;++j) op[j].t[i].val=A[i]; } for(i=1;i<=m;++i) { int a,b,c; scanf("%d%d%d",&a,&b,&c); op[c].link(a,b); pp[a][b]=pp[b][a]=c; lk[a][b]=lk[b][a]=1; } for(i=1;i<=K;++i) { int opt; scanf("%d",&opt); if(opt==0) { int x,y; scanf("%d%d",&x,&y); for(j=0;j<C;++j) op[j].makeroot(x), op[j].t[x].val=y, op[j].pushup(x); } if(opt==1) { int u,v,w; scanf("%d%d%d",&u,&v,&w); if(!lk[u][v]) { printf("No such edge.\n"); } else { int flag2=0,flag1=0; if(pp[u][v]==w) { printf("Success.\n"); } else if(op[w].find(u)==op[w].find(v)) { flag2=1; if(!op[w].check(u) || !op[w].check(v)) flag1=1; } else { op[w].makeroot(u); op[w].makeroot(v); if(op[w].check(u)&&op[w].check(v)) { op[w].link(u,v); op[pp[u][v]].cut(u,v); pp[u][v]=pp[v][u]=w; printf("Success.\n"); } else { flag1=1; } } if(flag2||flag1) { if(flag1) printf("Error 1.\n"); else printf("Error 2.\n"); } } } if(opt==2) { int c,u,v; scanf("%d%d%d",&c,&u,&v); if(op[c].find(u)!=op[c].find(v)) printf("-1\n"); else { op[c].split(u,v); printf("%d\n",op[c].t[v].max); } } } return 0; }