您的位置:首页 > 理论基础 > 计算机网络

BZOJ2816:[ZJOI2012]网络——题解

2018-04-02 15:55 274 查看

https://www.lydsy.com/JudgeOnline/problem.php?id=2816

https://www.luogu.org/problemnew/show/P2173

有一个无向图G,每个点有个权值,每条边有一个颜色。这个无向图满足以下两个条件:

  1. 对于任意节点连出去的边中,相同颜色的边不超过两条。

  2. 图中不存在同色的环,同色的环指相同颜色的边构成的环。

在这个图上,你要支持以下三种操作:

  1. 修改一个节点的权值。

  2. 修改一条边的颜色。

  3. 查询由颜色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]
,tr[C]
[2],d[C]
;
int rev[C]
,q
,key
,val[C]
,head
,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/+

+++++++++++++++++++++++++++++++++++++++++++

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: