思路显然,就是对每一个颜色建一棵LCT(有没有想过颜色多了怎么办)
讲一讲我从这道题里面get到的小技能。
判断连通性:
if(findroot(x)==findroot(y))return true; else return false;
还有一个比较坑的地方就是它修改颜色的时候可能跟以前相同,这里要特判。
看代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e4+10; int n,m,col,q,val[maxn]; struct LCT{ int p[maxn],f[maxn],c[maxn][5],mx[maxn],rev[maxn]; inline void pushup(int x){ mx[x]=max(val[x],max(mx[c[x][0]],mx[c[x][1]])); } inline void pushr(int x){ swap(c[x][0],c[x][1]); rev[x]^=1; } inline void pushdown(int x){ if(rev[x]){ if(c[x][0])pushr(c[x][0]); if(c[x][1])pushr(c[x][1]); rev[x]=0; } } inline int nroot(int x){ return c[f[x]][0]==x||c[f[x]][1]==x; } inline void pushall(int x){ if(nroot(x))pushall(f[x]); pushdown(x); } inline void rotate(int x){ int y=f[x],z=f[y],k=(c[y][1]==x),w=c[x][!k]; if(nroot(y))c[z][(c[z][1]==y)]=x;c[x][!k]=y;c[y][k]=w; if(w)f[w]=y;f[y]=x;f[x]=z; pushup(y); } inline void splay(int x){ pushall(x); while(nroot(x)){ int y=f[x],z=f[y]; if(nroot(y))rotate((c[y][0]==x)^(c[z][0]==y)?x:y); rotate(x); } pushup(x); } inline void access(int x){ for(int y=0;x;y=x,x=f[x]) splay(x),c[x][1]=y,pushup(x); } inline void makeroot(int x){ access(x);splay(x);pushr(x); } inline int findroot(int x){ access(x);splay(x); while(c[x][0])pushdown(x),x=c[x][0]; splay(x);return x; } inline void link(int x,int y){ makeroot(x); if(findroot(y)!=x)f[x]=y; } inline void cut(int x,int y){ makeroot(x); if(findroot(y)==x&&f[y]==x&&!c[y][0]){ f[y]=c[x][1]=0; pushup(x); } } inline void split(int x,int y){ makeroot(x);access(y);splay(y); } }k[15]; inline int read(){ int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x*f; } map<int,int>vis; int main(){ n=read(),m=read(),col=read(),q=read(); for(int i=1;i<=n;i++)val[i]=read(); int opt,x,y,z; for(int i=1;i<=m;i++){ x=read(),y=read(),z=read()+1; k[z].link(x,y); vis[x*10000+y]=vis[y*10000+x]=z; k[z].p[x]++;k[z].p[y]++; } for(int i=1;i<=q;i++){ opt=read(); if(opt==0){ x=read(),y=read(); for(int j=1;j<=col;j++) k[j].splay(x); val[x]=y; }else if(opt==1){ x=read(),y=read(),z=read()+1; if(!vis[x*10000+y])puts("No such edge."); else if(z==vis[x*10000+y])puts("Success."); else if(k[z].p[x]==2||k[z].p[y]==2)puts("Error 1."); else if(k[z].findroot(x)==k[z].findroot(y))puts("Error 2."); else{ k[vis[x*10000+y]].cut(x,y); k[z].link(x,y); k[vis[x*10000+y]].p[x]--; k[vis[x*10000+y]].p[y]--; k[z].p[x]++; k[z].p[y]++; vis[x*10000+y]=vis[y*10000+x]=z; puts("Success."); } }else{ z=read()+1,x=read(),y=read(); if(k[z].findroot(x)!=k[z].findroot(y))puts("-1"); else{ k[z].split(x,y); printf("%d ",k[z].mx[y]); } } } return 0; }
深深地感到自己的弱小。