• 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
    ",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
    ",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
    ",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
    ",t[c].query(v,u));
    		}
    	}
    
    
    	return 0;
    }
    
  • 相关阅读:
    Centos7.x做开机启动脚本
    贝叶斯方法之一
    R程序包
    c#调用R
    感悟--不可抗拒的行为
    IP等级
    词语
    关于editplus设置java和c#
    csc命令
    editplus配置csharp
  • 原文地址:https://www.cnblogs.com/wxyww/p/luogu2173.html
Copyright © 2020-2023  润新知