luogu4172 [WC2006]水管局长

就是用 lct 维护最小生成树
ref

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
typedef pair<int,int> par;
int n, m, q, val[200005], zdz[200005], ans[200005], ch[200005][2];
int fa[200005];
bool vis[100005], rev[200005];
map<par,int> mp;
struct Edge{
	int fro, too, val;
}edge[100005];
struct Ques{
	int opt, x, y;
}qu[100005];
bool cmp(Edge x, Edge y){
	return x.val<y.val;
}
bool isRoot(int x){
	return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
}
int getW(int x){
	return ch[fa[x]][1]==x;
}
void upd(int x){
	zdz[x] = val[x];
	if(edge[zdz[ch[x][0]]].val>edge[zdz[x]].val)
		zdz[x] = zdz[ch[x][0]];
	if(edge[zdz[ch[x][1]]].val>edge[zdz[x]].val)
		zdz[x] = zdz[ch[x][1]];
}
void pushDown(int x){
	if(rev[x]){
		swap(ch[x][0], ch[x][1]);
		rev[ch[x][0]] ^= 1;
		rev[ch[x][1]] ^= 1;
		rev[x] = false;
	}
}
void xf(int x){
	if(fa[x])	xf(fa[x]);
	pushDown(x);
}
void rotate(int x){
	int old=fa[x], oldf=fa[old], w=getW(x);
	if(!isRoot(old))	ch[oldf][ch[oldf][1]==old] = x;
	ch[old][w] = ch[x][w^1]; ch[x][w^1] = old;
	fa[ch[old][w]] = old; fa[ch[x][w^1]] = x; fa[x] = oldf;
	upd(old); upd(x);
}
void splay(int x){
	xf(x);
	while(!isRoot(x)){
		int f=fa[x];
		if(!isRoot(f))
			rotate(getW(x)==getW(f)?f:x);
		rotate(x);
	}
	upd(x);
}
void access(int x){
	int y=0;
	while(x){
		splay(x);
		ch[x][1] = y;
		upd(x);
		y = x;
		x = fa[x];
	}
}
int findroot(int x){
	access(x);
	splay(x);
	while(ch[x][0])
		x = ch[x][0];
	splay(x);
	return x;
}
void makeroot(int x){
	access(x);
	splay(x);
	rev[x] ^= 1;
}
void split(int x, int y){
	makeroot(x);
	access(y);
	splay(y);
}
void link(int x, int y){
	makeroot(x);
	fa[x] = y;
}
void cut(int x, int y){
	split(x, y);
	fa[x] = ch[y][0] = 0;
}
int main(){//anonymous Pro Regular
	cin>>n>>m>>q;
	for(int i=1; i<=m; i++){
		scanf("%d %d %d", &edge[i].fro, &edge[i].too, &edge[i].val);
		if(edge[i].fro>edge[i].too) swap(edge[i].fro, edge[i].too);
	}
	sort(edge+1, edge+1+m, cmp);
	for(int i=1; i<=m; i++)
		mp[make_pair(edge[i].fro, edge[i].too)] = i;
	for(int i=1; i<=q; i++){
		scanf("%d %d %d", &qu[i].opt, &qu[i].x, &qu[i].y);
		if(qu[i].x>qu[i].y) swap(qu[i].x, qu[i].y);
		if(qu[i].opt==2)
			vis[mp[make_pair(qu[i].x, qu[i].y)]] = true;
	}
	for(int i=n+1; i<=n+m; i++)
		val[i] = zdz[i] = i - n;
	int tmpcnt=0;
	for(int i=1; i<=m; i++){
		if(tmpcnt==n-1)	break;
		if(vis[i] || findroot(edge[i].fro)==findroot(edge[i].too))	continue;
		link(edge[i].fro, i+n); link(edge[i].too, i+n);
		tmpcnt++;
	}
	for(int i=q; i; i--){
		if(qu[i].opt==1){
			split(qu[i].x, qu[i].y);
			ans[i] = edge[zdz[qu[i].y]].val;
		}
		else{
			split(qu[i].x, qu[i].y);
			int idx=mp[make_pair(qu[i].x, qu[i].y)];
			int tmp=zdz[qu[i].y];
			if(edge[idx].val<edge[tmp].val){
				cut(edge[tmp].fro, tmp+n);
				cut(edge[tmp].too, tmp+n);
				link(edge[idx].fro, idx+n);
				link(edge[idx].too, idx+n);
			}
		}
	}
	for(int i=1; i<=q; i++)
		if(qu[i].opt==1)
			printf("%d\n", ans[i]);
	return 0;
}
posted @ 2018-05-31 07:52  poorpool  阅读(226)  评论(0编辑  收藏  举报