BZOJ2816:[ZJOI2012]网络——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2816
https://www.luogu.org/problemnew/show/P2173
有一个无向图G,每个点有个权值,每条边有一个颜色。这个无向图满足以下两个条件:
对于任意节点连出去的边中,相同颜色的边不超过两条。
图中不存在同色的环,同色的环指相同颜色的边构成的环。
在这个图上,你要支持以下三种操作:
修改一个节点的权值。
修改一条边的颜色。
查询由颜色c的边构成的图中,所有可能在节点u到节点v之间的简单路径上的节点的权值的最大值。
这题只要知道什么数据结构,就暴力大模拟即可。
那显然给你的每种颜色组成的图形是一条链,所以使用LCT。
然后对每种颜色建LCT即可。
(纯码农题没有板子情况下1.5h写完1A,这速度怕不是药丸?)
#include<algorithm> #include<iostream> #include<cstring> #include<cctype> #include<cstdio> #include<vector> #include<queue> #include<cmath> using namespace std; const int N=1e5+5; const int C=11; int n,m,c,k,r,fa[C][N],tr[C][N][2],d[C][N]; int rev[C][N],q[N],key[N],val[C][N],head[N],cnt=-1; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } inline bool get(int x,int w){ return tr[w][fa[w][x]][1]==x; } inline bool isroot(int x,int w){ if(!fa[w][x])return 1; return tr[w][fa[w][x]][0]!=x&&tr[w][fa[w][x]][1]!=x; } inline void pushrev(int x,int w){ if(!rev[w][x])return; swap(tr[w][x][0],tr[w][x][1]); if(tr[w][x][0])rev[w][tr[w][x][0]]^=1; if(tr[w][x][1])rev[w][tr[w][x][1]]^=1; rev[w][x]=0; } inline void upt(int x,int w){ val[w][x]=key[x]; if(tr[w][x][0])val[w][x]=max(val[w][x],val[w][tr[w][x][0]]); if(tr[w][x][1])val[w][x]=max(val[w][x],val[w][tr[w][x][1]]); } inline void rotate(int x,int w){ int y=fa[w][x],z=fa[w][y],which=get(x,w); if(z&&!isroot(y,w))tr[w][z][tr[w][z][1]==y]=x; tr[w][y][which]=tr[w][x][which^1];fa[w][tr[w][y][which]]=y; fa[w][y]=x;tr[w][x][which^1]=y;fa[w][x]=z; upt(y,w);upt(x,w); } inline void splay(int x,int w){ q[r=0]=x; for(int y=x;!isroot(y,w);y=fa[w][y])q[++r]=fa[w][y]; for(int i=r;i>=0;i--)pushrev(q[i],w); while(!isroot(x,w)){ if(!isroot(fa[w][x],w)) rotate(get(x,w)==get(fa[w][x],w)?fa[w][x]:x,w); rotate(x,w); } upt(x,w); } inline void access(int x,int w){ for(int y=0;x;y=x,x=fa[w][x]){ splay(x,w);tr[w][x][1]=y; if(y)fa[w][y]=x; } } inline int findroot(int x,int w){ access(x,w);splay(x,w); while(pushrev(x,w),tr[w][x][0])x=tr[w][x][0]; splay(x,w); return x; } inline void makeroot(int x,int w){ access(x,w);splay(x,w); rev[w][x]^=1; } inline void split(int x,int y,int w){ makeroot(x,w); access(y,w);splay(y,w); } inline void link(int x,int y,int w){ d[w][x]++;d[w][y]++; makeroot(x,w); fa[w][x]=y; } inline bool cut(int x,int y,int w){ split(x,y,w); if(tr[w][x][0]||tr[w][x][1]||fa[w][x]!=y||tr[w][y][get(x,w)^1])return 0; d[w][x]--;d[w][y]--; tr[w][y][0]=0;fa[w][x]=0; return 1; } int main(){ memset(head,-1,sizeof(head)); n=read(),m=read(),c=read(),k=read(); for(int i=1;i<=n;i++)key[i]=read(); for(int i=1;i<=m;i++){ int u=read(),v=read(),w=read(); link(u,v,w); } for(int i=1;i<=k;i++){ int op=read(); if(op==0){ int x=read(),y=read(); key[x]=y; for(int j=0;j<=c;j++){ access(x,j);splay(x,j); upt(x,j); } } if(op==1){ int u=read(),v=read(),w=read(); int ok=-1; for(int j=0;j<=c&&ok==-1;j++){ if(cut(u,v,j))ok=j; } if(ok==-1){ puts("No such edge."); continue; } if(d[w][u]>1||d[w][v]>1){ puts("Error 1."); link(u,v,ok); continue; } if(findroot(u,w)==findroot(v,w)){ puts("Error 2."); link(u,v,ok); continue; } puts("Success."); link(u,v,w); } if(op==2){ int w=read(),u=read(),v=read(); split(u,v,w); if(findroot(u,w)!=findroot(v,w)){ puts("-1"); continue; } split(u,v,w); printf("%d\n",val[w][v]); } } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++