【LCT】LGP2173 [ZJOI2012] 网络

版权声明:这是蒟蒻的BLOG,神犇转载也要吱一声哦~ https://blog.csdn.net/Dream_Lolita/article/details/89737867

【题目】
LG
给定一幅 n n 个点 m m 条边有点权,边有颜色的无向图。
Q Q 个操作支持:

  • 修改点权
  • 改变边的颜色
  • 询问仅看某种颜色时两点间最大点权。
    若一次 2 2 操作使得某种颜色的连通块不为森林,或没有这条边,则忽略此操作并输出相应的错误信息。

n 1 0 4 , m , Q 1 0 5 n\leq 10^4,m,Q\leq 10^5 ,颜色数 10 \leq 10

【解题思路】
观察到颜色数很少,而每种颜色一定是一个森林。
于是每种颜色维护一个 LCT \text{LCT} 即可。

【参考代码】

#include<bits/stdc++.h>
using namespace std;

const int N=10005;

namespace IO
{
	int read()
	{
		int ret=0;char c=getchar();
		while(!isdigit(c)) c=getchar();
		while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
		return ret;
	}
	void write(int x){if(x>9)write(x/10);putchar(x%10^48);}
	void writeln(int x){write(x);putchar('\n');}
}
using namespace IO;

namespace Data_Structure
{
	int col[N],val[N],st[N],top;
	struct LCT
	{
		#define ls ch[x][0]
		#define rs ch[x][1]
		int ch[N][2],fa[N],rev[N],mx[N],du[N];
		void pushup(int x){mx[x]=max(max(mx[ls],mx[rs]),val[x]);}
		void pushdown(int x){if(rev[x]){rev[x]^=1;rev[ls]^=1;rev[rs]^=1;swap(ls,rs);}}
		bool isroot(int x){return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;}
		int get(int x){return ch[fa[x]][1]==x;}
		void rotate(int x)
		{
			int y=fa[x],z=fa[y],k=get(x);
			if(!isroot(y)) ch[z][get(y)]=x;
			fa[ch[x][!k]]=y;fa[y]=x;fa[x]=z;
			ch[y][k]=ch[x][!k];ch[x][!k]=y;
			pushup(y);pushup(x);
		}
		void splay(int x)
		{
			st[top=1]=x;for(int t=x;!isroot(t);t=fa[t])st[++top]=fa[t];
			while(top) pushdown(st[top--]);
			while(!isroot(x))
			{
				int y=fa[x];
				if(!isroot(y)) rotate(get(y)==get(x)?y:x);
				rotate(x);
			}
		}
		void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),rs=y,pushup(x);}
		void makeroot(int x){access(x);splay(x);rev[x]^=1;}
		int findroot(int x){access(x);splay(x);while(ls)x=ls;return x;}
		void getedge(int x,int y){makeroot(x);access(y);splay(y);}
		void cut(int x,int y){--du[x];--du[y];getedge(x,y);fa[x]=ch[y][0]=0;}
		void link(int x,int y){++du[x];++du[y];makeroot(x);fa[x]=y;}
		#undef ls
		#undef rs
	}T[10];
}
using namespace Data_Structure;

namespace DreamLolita
{
	int n,m,C,Q;
	void modifyval()
	{
		int x=read(),v=read();
		for(int i=0;i<C;++i) T[i].access(x),T[i].splay(x);
		val[x]=v;
		for(int i=0;i<C;++i) T[i].pushup(x);
	}
	void modifyedge()
	{
		int x=read(),y=read(),z=read();
		for(int i=0;i<C;++i) if(T[i].findroot(x)==T[i].findroot(y))
		{
			T[i].getedge(x,y);
			if(T[i].ch[y][0]!=x || T[i].ch[x][1]) continue;
			if(i==z) puts("Success.");
			else if(T[z].du[x]==2 || T[z].du[y]==2) puts("Error 1.");
			else if(T[z].findroot(x)==T[z].findroot(y)) puts("Error 2.");
			else T[i].cut(x,y),T[z].link(x,y),puts("Success.");
			return;
		}
		puts("No such edge.");
	}
	void calcans()
	{
		int z=read(),x=read(),y=read();
		if(T[z].findroot(x)!=T[z].findroot(y)) puts("-1");
		else T[z].getedge(x,y),printf("%d\n",T[z].mx[y]);
	}
	void solution()
	{
		n=read();m=read();C=read();Q=read();
		for(int i=1;i<=n;++i) val[i]=read();
		for(int i=1,u,v;i<=m;++i) u=read(),v=read(),T[read()].link(u,v);
		while(Q--)
		{
			int op=read();
			if(!op) modifyval();
			else if(op==1) modifyedge();
			else calcans();
		} 
	}
}

int main()
{
#ifdef Durant_Lee
	freopen("LGP2173.in","r",stdin);
	freopen("LGP2173.out","w",stdout);
#endif
	DreamLolita::solution();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Dream_Lolita/article/details/89737867