1. 程式人生 > >[WC2006]水管局長

[WC2006]水管局長

水管局長

LCT

  題目連結:https://www.luogu.org/problemnew/show/P4172#sub

  顯然兩個點的路徑上的邊最大要最小在該圖最小生成樹上

  正刪倒加,倒著做變成加邊操作

  加邊時判斷一下是否能形成更優的生成樹,用LCT刪除和連線操作即可

  1 #include<iostream>
  2 #include<cstdio>
  3 using namespace std;
  4 const int M=2e5+9;
  5 int n,m,q;
  6 int fr[M],to[M],e[1009
][1009],d[1009][1009]; 7 int O[M],X[M],Y[M]; 8 bool vis[1009][1009],rev[M]; 9 int f[M],c[M][2],Ma[M],s[M],ans[M]; 10 bool bol=0; 11 int read(){ 12 int rex=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){rex=rex*10
+ch-'0';ch=getchar();} 15 return rex*f; 16 } 17 bool isroot(int x){ 18 return c[f[x]][0]!=x&&c[f[x]][1]!=x; 19 } 20 int Max(int x,int y){ 21 return e[fr[x]][to[x]]<e[fr[y]][to[y]]?y:x; 22 } 23 void pushup(int x){ 24 Ma[x]=Max(Max(Ma[c[x][0]],Ma[c[x][1]]),x); 25 } 26
void pushdown(int x){ 27 if(rev[x]){ 28 swap(c[x][0],c[x][1]); 29 rev[x]^=1,rev[c[x][0]]^=1,rev[c[x][1]]^=1; 30 } 31 } 32 void rotate(int x){ 33 int y=f[x],z=f[y],k=c[y][1]==x,ch=c[x][k^1]; 34 if(!isroot(y))c[z][c[z][1]==y]=x;f[x]=z; 35 c[y][k]=ch;f[ch]=y; 36 c[x][k^1]=y;f[y]=x; 37 pushup(y),pushup(x); 38 39 } 40 void splay(int x){ 41 int top=0,u=x; 42 while(!isroot(u))s[++top]=u,u=f[u];s[++top]=u; 43 while(top)pushdown(s[top--]); 44 for(int y=f[x];!isroot(x);y=f[x]){ 45 if(!isroot(y)) 46 rotate(((c[f[y]][1]==y)==(c[y][1]==x))?y:x); 47 rotate(x); 48 } 49 } 50 void access(int x){for(int t=0;x;t=x,x=f[x]){splay(x);c[x][1]=t;pushup(x);}} 51 void makeroot(int x){access(x),splay(x),rev[x]^=1;} 52 int findroot(int x){access(x);splay(x);while(c[x][0])x=c[x][0];return x;} 53 void split(int x,int y){makeroot(x),access(y),splay(y);} 54 void link(int x,int y){makeroot(x),f[x]=y;} 55 void cut(int x,int y){split(x,y);c[y][0]=0;f[x]=0;pushup(y);} 56 int main(){ 57 n=read(),m=read(),q=read(); 58 for(int i=1,u,v;i<=m;++i){ 59 fr[i]=u=read(),to[i]=v=read(); 60 d[u][v]=d[v][u]=i;Ma[i]=i; 61 e[u][v]=e[v][u]=read(); 62 } 63 for(int i=1;i<=q;++i){ 64 O[i]=read(),X[i]=read(),Y[i]=read(); 65 if(O[i]==2)vis[X[i]][Y[i]]=vis[Y[i]][X[i]]=1; 66 } 67 for(int i=1;i<=m;++i){ 68 int x=fr[i]+m,y=to[i]+m; 69 if(!vis[fr[i]][to[i]]){ 70 if(findroot(x)!=findroot(y)){ 71 link(x,i); 72 link(y,i); 73 } 74 else { 75 split(x,y);int v=Ma[y]; 76 if(Max(v,i)==v){ 77 cut(v,fr[v]+m); 78 cut(v,to[v]+m); 79 link(x,i); 80 link(y,i); 81 } 82 } 83 } 84 } 85 for(int i=q,x,y;i>=1;--i){ 86 x=X[i]+m,y=Y[i]+m;int u=d[X[i]][Y[i]]; 87 if(O[i]==1){ 88 split(x,y);int v=Ma[y]; 89 ans[i]=e[fr[v]][to[v]]; 90 } 91 if(O[i]==2){ 92 if(findroot(x)!=findroot(y)){ 93 link(x,i); 94 link(y,i); 95 } 96 else { 97 split(x,y);int v=Ma[y]; 98 if(Max(v,u)==v){ 99 cut(v,fr[v]+m); 100 cut(v,to[v]+m); 101 link(x,u); 102 link(y,u); 103 } 104 } 105 } 106 } 107 for(int i=1;i<=q;++i){ 108 if(O[i]==1)printf("%d\n",ans[i]); 109 } 110 return 0; 111 }
View Code