luogu2173 [ZJOI2012]网络

题目链接

problem

给出一个无向图,每条边有一种颜色。每种颜色都构成一个森林。需要完成以下操作。

  • 修改点权
  • 修改边的颜色
  • 询问某种颜色的森林中某条路径上点权最大值

solution

颜色数量不超过10,所以对于每种颜色建一棵LCT。
修改点权,就对每种颜色的LCT都修改。
修改边的颜色,就将原来颜色的LCT中这条边断掉,在新颜色的LCT中加上。这里需要判断加入边后是否还满足是森林,所以需要统计每个点连出去的各种颜色点的数量。还要判断是否会形成环,只要判断原来两点是否在同一棵树中。
询问操作则直接询问即可。

code

/*
* @Author: wxyww
* @Date: 2020-02-26 07:36:20
* @Last Modified time: 2020-02-26 09:21:59
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define ls TR[cur].ch[0]
#define rs TR[cur].ch[1]
const int N = 10010;
ll read() {
	ll x=0,f=1;char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9') {
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}

struct LCT {
	struct node {
		int ch[2],val,rev,mx,pre;
	}TR[N];
	int isroot(int cur) {
		return TR[TR[cur].pre].ch[0] != cur && TR[TR[cur].pre].ch[1] != cur;
	}
	int getwh(int cur) {
		return TR[TR[cur].pre].ch[1] == cur;
	}
	void up(int cur) {
		TR[cur].mx = max(TR[ls].mx,max(TR[rs].mx,TR[cur].val));
	}
	void pushdown(int cur) {
		if(TR[cur].rev) {
			TR[ls].rev ^= 1;TR[rs].rev ^= 1;
			swap(ls,rs);
			TR[cur].rev = 0;
		}
	}
void rotate(int cur) {
	int fa = TR[cur].pre,gr = TR[fa].pre,f = getwh(cur);

	if(!isroot(fa)) TR[gr].ch[getwh(fa)] = cur;
	TR[cur].pre = gr;
	if(TR[cur].ch[f ^ 1]) TR[TR[cur].ch[f ^ 1]].pre = fa;
	TR[fa].ch[f] = TR[cur].ch[f ^ 1];
	TR[fa].pre = cur;TR[cur].ch[f ^ 1] = fa;
	up(fa);up(cur);
}
	int sta[N],top;
	void splay(int cur) {
		sta[++top] = cur;

		for(int i = cur;!isroot(i);i = TR[i].pre) {
			// printf("%d\n",i);
			sta[++top] = TR[i].pre;
		}
		while(top) pushdown(sta[top--]);

		while(!isroot(cur)) {
			if(!isroot(TR[cur].pre)) {
				if(getwh(TR[cur].pre) == getwh(cur)) rotate(TR[cur].pre);
				else rotate(cur);
			}
			rotate(cur);
		}
	}

	void access(int cur) {
		for(int t = 0;cur;t = cur,cur = TR[cur].pre) {

			splay(cur);rs = t;up(cur);
		}
	}
	void makeroot(int cur) {
		access(cur);

		splay(cur);
		TR[cur].rev ^= 1;
	}
	void link(int x,int y) {
		// printf("%d\n",x);
		makeroot(x);TR[x].pre = y;
	}

	void cut(int x,int cur) {
		makeroot(x);access(cur);
		splay(cur);
		ls = TR[ls].pre = 0;
		up(cur);
	}

	void update(int cur,int c) {
		makeroot(cur);TR[cur].val = c;
		up(cur);
	}
	int find(int cur) {
		access(cur);splay(cur);
		while(ls) cur = ls;
		return cur;
	}
	int query(int x,int y) {
		if(find(x) != find(y)) return -1;
		makeroot(x);access(y);splay(y);
		return TR[y].mx;
	}
}t[10];


#define pi pair<int,int>
map<pi,int>ma;
int num[N][11];
int main() {
	// freopen("1.in","r",stdin);
	int n = read(),m = read(),C = read(),Q = read();
	for(int i = 1;i <= n;++i) {
		int x = read();
		for(int j = 0;j < C;++j) 
		t[j].TR[i].mx = t[j].TR[i].val = x;
	}
	for(int i = 1;i <= m;++i) {
		int u = read(),v = read(),w = read();
		ma[make_pair(u,v)] = ma[make_pair(v,u)] = w;
		num[u][w]++;num[v][w]++;

		t[w].link(u,v);
		// puts("!!!");
	}

	while(Q--) {
		int opt = read();
		if(opt == 0) {
			int x = read(),y = read();
			for(int j = 0;j < C;++j) {
				t[j].update(x,y);
			}
		}

		if(opt == 1) {
			int u = read(),v = read(),w = read();
			if(!ma.count(make_pair(u,v))) {
				puts("No such edge.");continue;
			}
			int tmp = ma[make_pair(u,v)];
			if(tmp == w) {puts("Success.");continue;}
			
			if(num[u][w] + 1 > 2 || num[v][w] + 1 > 2) {puts("Error 1.");continue;}

			// printf("%d %d\n",t[w].find(u),t[w].find(v));
			if(t[w].find(u) == t[w].find(v)) {
				puts("Error 2.");continue;}


			puts("Success.");

			t[tmp].cut(u,v);

			num[u][tmp]--;num[v][tmp]--;

			num[u][w]++;num[v][w]++;
			t[w].link(u,v);
			ma[make_pair(u,v)] = ma[make_pair(v,u)] = w;
		}


		if(opt == 2) {
			int c = read(),u = read(),v = read();
			printf("%d\n",t[c].query(v,u));
		}
	}


	return 0;
}
posted @ 2020-02-26 16:24  wxyww  阅读(172)  评论(0编辑  收藏  举报