【BZOJ2816】【ZJOI2012】网络(Link-Cut Tree)

【BZOJ2816】【ZJOI2012】网络(Link-Cut Tree)

题面

题目描述

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

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

图中不存在同色的环,同色的环指相同颜色的边构成的环。
在这个图上,你要支持以下三种操作:

修改一个节点的权值。

修改一条边的颜色。

查询由颜色c的边构成的图中,所有可能在节点u到节点v之间的简单路径上的节点的权值的最大值。

输入输出格式

输入格式:
输入文件network.in的第一行包含四个正整数N, M, C, K,其中N为节点个数,M为边数,C为边的颜色数,K为操作数。

接下来N行,每行一个正整数vi,为节点i的权值。

之后M行,每行三个正整数u, v, w,为一条连接节点u和节点v的边,颜色为w。满足1 ≤ u, v ≤ N,0 ≤ w < C,保证u ≠ v,且任意两个节点之间最多存在一条边(无论颜色)。

最后K行,每行表示一个操作。每行的第一个整数k表示操作类型。

k = 0为修改节点权值操作,之后两个正整数x和y,表示将节点x的权值vx修改为y。

k = 1为修改边的颜色操作,之后三个正整数u, v和w,表示将连接节点u和节点v的边的颜色修改为颜色w。满足0 ≤ w < C。

k = 2为查询操作,之后三个正整数c, u和v,表示查询所有可能在节点u到节点v之间的由颜色c构成的简单路径上的节点的权值的最大值。如果不存在u和v之间不存在由颜色c构成的路径,那么输出“-1”。
输出格式:
输出文件network.out包含若干行,每行输出一个对应的信息。

对于修改节点权值操作,不需要输出信息。

对于修改边的颜色操作,按以下几类输出:
a) 若不存在连接节点u和节点v的边,输出“No such edge.”。

b) 若修改后不满足条件1,不修改边的颜色,并输出“Error 1.”。

c) 若修改后不满足条件2,不修改边的颜色,并输出“Error 2.”。

d) 其他情况,成功修改边的颜色,并输出“Success.”。

输出满足条件的第一条信息即可,即若同时满足b和c,则只需要输出“Error 1.”。

对于查询操作,直接输出一个整数。

输入输出样例

输入样例#1:
4 5 2 7
1
2
3
4
1 2 0
1 3 1
2 3 0
2 4 1
3 4 0
2 0 1 4
1 1 2 1
1 4 3 1
2 0 1 4
1 2 3 1
0 2 5
2 1 1 4
输出样例#1:
4
Success.
Error 2.
-1
Error 1.
5

题解

考虑(C<=10)
那么, 暴力维护(C)棵树即可
直接(LCT)维护即可
细节真的是有点多。。。
这道题目慢慢做。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 11000
#define fat t[x].ff
#define lson t[x].ch[0]
#define rson t[x].ch[1]
inline int read()
{
    int x=0,t=1;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int S[MAX],top;
struct N{int u,v;};
int n,m,C,K,val[MAX];
int color[MAX][11];
bool operator<(N a,N b)
{
	if(a.u!=b.u)return a.u<b.u;
	return a.v<b.v;
}
map<N,int> MM;
struct Node
{
	int ch[2],ff;
	int mm,val,rev; 
};
struct LCT
{
	struct Node t[MAX];
	void pushup(int x){t[x].mm=max(t[lson].mm,t[rson].mm);t[x].mm=max(t[x].mm,t[x].val);}
	bool isroot(int x){return t[fat].ch[0]!=x&&t[fat].ch[1]!=x;}
	void pushdown(int x)
	{
		if(!t[x].rev)return;
		swap(lson,rson);
		t[lson].rev^=1;t[rson].rev^=1;
		t[x].rev^=1;
	}
	void rotate(int x)
	{
		int y=t[x].ff,z=t[y].ff;
		int k=t[y].ch[1]==x;
		if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
		t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
		t[x].ch[k^1]=y;t[y].ff=x;	
		pushup(y);pushup(x);	
	}
	void Splay(int x)
	{
		S[top=1]=x;
		for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff;
		while(top)pushdown(S[top--]);
		while(!isroot(x))
		{
			int y=t[x].ff,z=t[y].ff;
			if(!isroot(y))
				(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
			rotate(x);
		}
	}
	void access(int x){for(int y=0;x;y=x,x=t[x].ff)Splay(x),t[x].ch[1]=y,pushup(x);}
	void makeroot(int x){access(x);Splay(x);t[x].rev^=1;}
	void split(int x,int y){makeroot(x);access(y);Splay(y);}
	void cut(int x,int y){split(x,y);t[y].ch[0]=t[x].ff=0;}
	void link(int x,int y){makeroot(x);t[x].ff=y;}
	int findroot(int x){access(x);Splay(x);while(lson)x=lson;return x;}
}LCT[11];
int main()
{
    n=read();m=read();C=read();K=read();
    for(int i=1;i<=n;++i)val[i]=read();
    for(int i=1;i<=n;++i)
    	for(int j=1;j<=C;++j)
    		LCT[j].t[i].val=val[i];
    for(int i=1,u,v,w;i<=m;++i)
    {
    	u=read(),v=read(),w=read()+1;
    	MM[(N){u,v}]=w;
    	MM[(N){v,u}]=w;
    	color[u][w]++;color[v][w]++;
    	LCT[w].link(u,v);
    }
    while(K--)
    {
    	int opt=read();
    	if(opt==0)
    	{
    		int x=read();val[x]=read();
    		for(int i=1;i<=C;++i)
    		{
    			LCT[i].access(x);
    			LCT[i].Splay(x);
				LCT[i].t[x].val=val[x];
			}
    	}
    	else if(opt==1)
    	{
    		int u=read(),v=read(),w=read()+1;
    		int G=MM[(N){u,v}];
    		if(!G){puts("No such edge.");continue;}
    		if(G==w){puts("Success.");continue;}
			if(color[u][w]>1||color[v][w]>1){puts("Error 1.");continue;}
    		if(LCT[w].findroot(u)==LCT[w].findroot(v)){puts("Error 2.");continue;}
    		color[u][w]++;color[v][w]++;
    		color[u][G]--;color[v][G]--;
    		MM[(N){u,v}]=w;MM[(N){v,u}]=w;
    		LCT[G].cut(u,v);
    		LCT[w].link(u,v);
    		puts("Success.");
		}
    	else
    	{
    		int w=read()+1,u=read(),v=read();
    		if(LCT[w].findroot(u)!=LCT[w].findroot(v)){puts("-1");continue;}
    		LCT[w].split(u,v);
    		printf("%d
",LCT[w].t[v].mm);
    	}
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cjyyb/p/7954289.html