题意:
一个网络支持一下操作:
修改一个节点的权值。
修改一条边的颜色。
查询由颜色c的边构成的图中,所有可能在节点u到节点v之间的简单路径上的节点的权值的最大值。
做法:对于每一种颜色,用一棵Splay维护最大值即可。
注意:rotate请不要打错(grandfa的儿子要另外判断左右)。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
const int maxc=13;
const int maxn=10010;
int n,m,c,k;
struct Splay{
int ch[maxn][2],Max[maxn],rev[maxn];
int deg[maxn],val[maxn];
int fa[maxn];
int root(int x){
while(fa[x]){
x=fa[x];
}
return x;
}
void maintain(int u){
Max[u]=val[u];
if(ch[u][0])Max[u]=max(Max[u],Max[ch[u][0]]);
if(ch[u][1])Max[u]=max(Max[u],Max[ch[u][1]]);
}
void rotate(int u){
int v=fa[u];
int l=(u==ch[v][1]);
fa[u]=fa[v];
if(fa[v]) ch[fa[v]][ch[fa[v]][1]==v]=u;
ch[v][l]=ch[u][l^1];fa[ch[u][l^1]]=v;
fa[v]=u;ch[u][l^1]=v;
maintain(v);
maintain(u);
}
void pushdown(int u){
if(rev[u]){
if(ch[u][0])rev[ch[u][0]]^=1;
if(ch[u][1])rev[ch[u][1]]^=1;
rev[u]=0;
swap(ch[u][0],ch[u][1]);
}
}
void push(int u){
if(fa[u]) push(fa[u]);
pushdown(u);
}
void splay(int u,int v){
push(u);
while(fa[u]!=v){
if(fa[fa[u]]!=v) rotate(fa[u]);
rotate(u);
}
}
bool link(int x,int y,bool out=true){
if(deg[x]>=2 || deg[y]>=2){
printf("Error 1.\n");return false;
}
if(root(x)==root(y)){
printf("Error 2.\n");return false;
}
deg[x]++;deg[y]++;
splay(x,0);splay(y,0);
if(ch[y][0]) rev[y]^=1,pushdown(y);
if(ch[x][1]) rev[x]^=1,pushdown(x);
fa[x]=y;
ch[y][0]=x;
maintain(x);
if(out) printf("Success.\n");
return true;
}
void del(int x,int y){
splay(x,0);splay(y,x);
fa[y]=0;
ch[x][y==ch[x][1]]=0;
deg[x]--;deg[y]--;
maintain(x);
}
void query(int x,int y){
if(root(x)!=root(y)){
printf("-1\n");return;
}
if(x==y){
printf("%d\n",val[x]);return;
}
splay(y,0);splay(x,y);
printf("%d\n",max(max(val[x],val[y]),Max[ch[x][x==ch[y][0]]]));
}
void update(int x,int y){
splay(x,0);
val[x]=y;
maintain(x);
}
}tree[maxc];
map<int,int>color[maxn];
int main(){
freopen("txt.in","r",stdin);
freopen("txt.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&c,&k);
for(int i=1;i<=n;i++){
scanf("%d",&tree[0].val[i]);
for(int j=0;j<c;j++){
tree[j].val[i]=tree[j].Max[i]=tree[0].val[i];
}
}
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
color[u][v]=color[v][u]=w;
tree[w].link(u,v,0);
}
for(int i=1;i<=k;i++){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==0){
for(int j=0;j<c;j++) tree[j].update(x,y);
}else if(op==1){
int w;
scanf("%d",&w);
if(!color[x].count(y)) printf("No such edge.\n");
else{
tree[color[x][y]].del(x,y);
if(!tree[w].link(x,y)) tree[color[x][y]].link(x,y,0);
else color[x][y]=color[y][x]=w;
}
}else{
int z;
scanf("%d",&z);
tree[x].query(y,z);
}
}
return 0;
}
^_^