zoukankan      html  css  js  c++  java
  • Luogu2542 [AHOI2005]航线规划

    Link

    Solution

    LCT维护边双的裸题。每次的答案是路径上边双数量-1。

    维护边双可以用并查集维护,每次操作就直接作用在边双的代表元素上就行了。因为怕自己漏掉一些(find()),导致没有在代表元素上操作,干脆就丧心病狂地在进入任意函数的时候都(find())一遍(反正复杂度也很低就是了)。当然除了缩点的函数(combine())。还有,似乎涉及到父亲的都需要(find())

    另外就是缩点之后代表元素要继承splay根节点的父亲,然后实儿子全都断掉。因为缩点就是把整个splay中的点缩成一个点,所以原本的实边关系都消失,只剩下虚边关系。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define REP(i,a,b) for(int i=(a),ed=(b);i<=ed;++i)
    inline int read(){
    	register int x=0,f=1;register char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
    	while(isdigit(ch)){x=x*10+(ch^'0');ch=getchar();}
    	return f?x:-x;
    }
    
    const int N=3e4+10,M=1e5+10;
    int n,m,t,ans[N],tp;
    map<pair<int,int>,int> h;
    struct node{int op,x,y;}e[M],q[M];
    
    namespace LinkCutTree{
    	int fa[N],ch[N][2],f[N],r[N],s[N];
    	inline int find(int x){return f[x]=f[x]==x?f[x]:find(f[x]);}
    	inline void pushup(int x){s[x]=s[ch[x][0]]+s[ch[x][1]]+1;}
    	inline void pushr(int x){swap(ch[x][0],ch[x][1]),r[x]^=1;}
    	inline void pushdown(int x){if(r[x])pushr(ch[x][0]),pushr(ch[x][1]),r[x]=0;}
    	inline int getdir(int x){return x==ch[find(fa[x])][1];}
    	inline bool noroot(int x){return x==ch[find(fa[x])][0]||x==ch[find(fa[x])][1];}
    	inline void rotate(int x){
    		x=find(x);int f=find(fa[x]),p=find(fa[f]),k=getdir(x),s=ch[x][!k];
    		ch[x][!k]=f;ch[f][k]=s;if(noroot(f))ch[p][getdir(f)]=x;
    		fa[f]=x;fa[x]=p;if(s)fa[s]=f;
    		pushup(f);
    	}
    	inline void splay(int x){
    		static int stk[N];
    		x=find(x);int tp=0,y=x;stk[++tp]=y;
    		while(noroot(y))stk[++tp]=y=find(fa[y]);
    		while(tp)pushdown(stk[tp--]);
    		for(int f=find(fa[x]);noroot(x);rotate(x),f=find(fa[x]))
    			if(noroot(f))rotate(getdir(f)==getdir(x)?f:x);
    		pushup(x);
    	}
    	inline void access(int x){
    		x=find(x);
    		for(int y=0;x;y=x,x=find(fa[x]))
    			splay(x),ch[x][1]=y,pushup(x);
    	}
    	inline void makeroot(int x){
    		x=find(x);access(x);splay(x);pushr(x);
    	}
    	inline int findroot(int x){
    		x=find(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){
    		x=find(x),y=find(y);makeroot(x);access(y);splay(y);
    	}
    	inline void combine(int x){
    		pushdown(x);
    		if(ch[x][0])f[find(ch[x][0])]=find(x),combine(ch[x][0]);
    		if(ch[x][1])f[find(ch[x][1])]=find(x),combine(ch[x][1]);
    	}
    	inline void link(int x,int y){
    		x=find(x),y=find(y);if(x==y)return;
    		makeroot(x);
    		if(findroot(y)^x)fa[x]=y;
    		else{
    			split(x,y);combine(y);
    			int t=find(y);
    			fa[t]=find(fa[y]);ch[t][0]=ch[t][1]=0;
    			pushup(t);
    		}
    	}
    }using namespace LinkCutTree;
    
    int main(){
    	n=read(),m=read();
    	REP(i,1,m){
    		e[i]=(node){0,read(),read()};
    		if(e[i].x>e[i].y)swap(e[i].x,e[i].y);
    		h[make_pair(e[i].x,e[i].y)]=i;
    	}
    	while(1){
    		int op=read();if(!~op)break;
    		q[++t]=(node){op,read(),read()};
    		if(q[t].x>q[t].y)swap(q[t].x,q[t].y);
    		if(!op)e[h[make_pair(q[t].x,q[t].y)]].op=1;
    	}
    	REP(i,1,n)f[i]=i;
    	REP(i,1,m)if(!e[i].op)link(e[i].x,e[i].y);
    	while(t){
    		int x=find(q[t].x),y=find(q[t].y);
    		if(q[t].op){
    			split(x,y);
    			ans[++tp]=s[y]-1;
    		}
    		else link(x,y);
    		--t;
    	}
    	while(tp)printf("%d
    ",ans[tp--]);
    	return 0;
    }
    
    
  • 相关阅读:
    arcgis api 3.x for js 入门开发系列八聚合效果(附源码下载)
    arcgis api 3.x for js 入门开发系列七图层控制(附源码下载)
    arcgis api 3.x for js 入门开发系列六地图分屏对比(附源码下载)
    arcgis api 3.x for js 入门开发系列五地图态势标绘(附源码下载)
    arcgis api 3.x for js 入门开发系列四地图查询(附源码下载)
    Java里面获取当前服务器的IP地址
    Flutter at Google I/O 2018
    Modbus RTU 协议使用汇总
    plsql 创建表空间、用户、赋予权限
    Oracle:ODP.NET Managed 小试牛刀
  • 原文地址:https://www.cnblogs.com/fruitea/p/12129079.html
Copyright © 2011-2022 走看看