zoukankan      html  css  js  c++  java
  • 【洛谷P4172】[WC2006]水管局长【LCT】

    传送门

    Solution

    查询一条最大边权最小的路径,且要支持删边,我们可以想到用(LCT)维护最小生成树,查询(x,y)时就(split(x,y)),然后输出这条链上最大的边权即可。

    维护边权我们可以将每条边都看作一个新的点(x),从原边的(2)个端点向(x)连边,将(x)的点权置为原边权,这样我们就只需要维护链上的最大点权,这就很好做了。

    但是删边对最小生成树的影响让我们觉得有些棘手,考虑离线下来倒着处理,改删边为加边,注意到每加入一条边(()(u,v,w))就会导致最小生成树上出现一个环,根据最小生成树的基本性质,我们此时只要删掉换上的边权最大的边就能得到新的最小生成树。

    于是我们直接查询最小生成树上(u,v)链上的最大值,将它与(w)比大小,如果(w)更大,直接跳过,否则将边权最大的那条边(cut)掉并(link)新边即可。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e5+10;
    int n,mx[N],val[N],pos[N],ch[N][2],fa[N],rev[N];
    inline bool which(int x){return ch[fa[x]][1]==x;}
    inline void pushup(int x){
    	mx[x]=val[x];pos[x]=x;
    	if(mx[ch[x][0]]>mx[x]) mx[x]=mx[ch[x][0]],pos[x]=pos[ch[x][0]];
    	if(mx[ch[x][1]]>mx[x]) mx[x]=mx[ch[x][1]],pos[x]=pos[ch[x][1]];
    }
    inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    inline void rever(int x){
    	swap(ch[x][0],ch[x][1]);
    	rev[x]^=1;
    }
    inline void pushdown(int x){
    	if(!rev[x]) return ;
    	if(ch[x][0]) rever(ch[x][0]);
    	if(ch[x][1]) rever(ch[x][1]);
    	rev[x]=0;
    }
    inline void Rotate(int x){
    	int y=fa[x],z=fa[y],wx=which(x),wy=which(y);
    	if(!isroot(y)) ch[z][wy]=x;fa[x]=z;
    	ch[y][wx]=ch[x][wx^1];
    	if(ch[y][wx]) fa[ch[y][wx]]=y;
    	ch[x][wx^1]=y;fa[y]=x;
    	pushup(y);
    }
    int stk[N],top;
    inline void Splay(int x){
    	int now=x;
    	stk[top=1]=now;
    	while(!isroot(now)) now=fa[now],stk[++top]=now;
    	while(top) pushdown(stk[top--]);
    	while(!isroot(x)){
    		int y=fa[x];
    		if(!isroot(y)){
    			if(which(x)==which(y)) Rotate(y);
    			else Rotate(x);
    		}Rotate(x);
    	}
    	pushup(x); 
    } 
    inline void access(int x){
    	for(int last=0;x;last=x,x=fa[x])
    		Splay(x),ch[x][1]=last,pushup(x);
    }
    inline void makeroot(int x){
    	access(x);Splay(x);
    	rever(x);
    }
    inline int findroot(int x){
    	access(x);Splay(x);
    	while(ch[x][0]) pushdown(x),x=ch[x][0];
    	Splay(x);
    	return x;
    }
    inline void split(int x,int y){
    	makeroot(x);access(y);
    	Splay(y);
    }
    inline void link(int x,int y){
    	makeroot(x);
    	fa[x]=y;
    }
    inline void cut(int x,int y){
    	split(x,y);
    	fa[x]=ch[y][0]=0;
    	pushup(y);
    }
    struct node{
    	int u,v,w;
    }e[N],p[N]; 
    int m,q,cnt,sum,op[N],x[N],y[N],pd[1010][1010],g[1010][1010],pa[N],ans[N];
    pair<int,int> wh[N];
    struct cmp{
    	inline bool operator ()(node x,node y){return x.w<y.w;}
    };
    inline int find(int x){return pa[x]==x?x:pa[x]=find(pa[x]);}
    int main(){
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i=1;i<=m;++i){
    		scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    		if(e[i].u>e[i].v) swap(e[i].u,e[i].v);
    		g[e[i].u][e[i].v]=e[i].w;
    	}
    	for(int i=1;i<=q;++i){
    		scanf("%d%d%d",&op[i],&x[i],&y[i]);
    		if(op[i]==1) continue;
    		if(x[i]>y[i]) swap(x[i],y[i]);
    		if(g[x[i]][y[i]]>0) pd[x[i]][y[i]]=1;
    	}
    	for(int i=1;i<=m;++i){
    		if(pd[e[i].u][e[i].v]) continue;
    		p[++cnt]=e[i];
    	}
    	sort(p+1,p+cnt+1,cmp());
    	sum=n;
    	for(int i=1;i<=n;++i) pa[i]=i;
    	int tot=0;
    	for(int i=1;i<=cnt;++i){
    		int fx=find(p[i].u),fy=find(p[i].v);
    		if(fx==fy) continue;
    		pa[fx]=fy;++tot;
    		++sum;val[sum]=p[i].w;
    		wh[sum]=make_pair(p[i].u,p[i].v);
    		link(p[i].u,sum);link(p[i].v,sum);
    		if(tot==n-1) break;
    	}
    	for(int i=q;i>=1;--i){
    		if(op[i]==1){
    			split(x[i],y[i]);
    			ans[i]=mx[y[i]];
    		}		
    		else{
    			int t=g[x[i]][y[i]];
    			split(x[i],y[i]);
    			if(mx[y[i]]<t) continue;
    			int p=pos[y[i]];
    			cut(wh[p].first,p);
    			cut(wh[p].second,p);
    			++sum;val[sum]=t;wh[sum]=make_pair(x[i],y[i]);
    			link(x[i],sum);link(y[i],sum); 
    		}
    	}
    	for(int i=1;i<=q;++i)
    		if(op[i]==1)
    			printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    《简养脑》读书笔记
    如何用86天考上研究生
    Improving your submission -- Kaggle Competitions
    Getting started with Kaggle -- Kaggle Competitions
    入门机器学习
    《世界因你不同》读书笔记
    [转载]Python 包构建教程
    [转载] Pytorch拓展进阶(二):Pytorch结合C++以及Cuda拓展
    集合不能存放重复元素
    在jupyter notebook中绘制KITTI三维散点图
  • 原文地址:https://www.cnblogs.com/tqxboomzero/p/14243279.html
Copyright © 2011-2022 走看看