zoukankan      html  css  js  c++  java
  • 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
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    C#实现函数根据返回类型重载
    自己动手实现Expression翻译器 – Part Ⅱ
    ld编译链接时默认搜索路径
    出游
    常用网络命令(转贴)
    redhat6.3企业版安装oracle11g过程
    sqlserver2000版本识别
    考IQ的推断题-生日几何?
    Microsoft Visual Studio .NET 系统必备
    101~200之间的素数
  • 原文地址:https://www.cnblogs.com/poorpool/p/9114693.html
Copyright © 2011-2022 走看看