zoukankan      html  css  js  c++  java
  • P4334 [COI2007] Policija

    P4334 [COI2007] Policija

    题意

    一个无重边的无向图,每次询问删掉一条边或删掉一个点后两个点是否联通。

    思路

    连通性问题,我们可以考虑使用广义圆方树解决。

    1. 对于删掉一个点的情况:

    我们先跑 tarjan 建出圆方树。如何判断两点在删去一个点后在树上的连通性?当且仅当被删去的点在两点间的路径上。根据圆方树的性质,如果被删点在一个点双连通分量中,它是符合上面的判断条件的。

    所以,我们只需要建出圆方树,判断这个点是否在询问的两点间的路径上就行了。

    1. 对于删掉一条边的情况:

    考虑我们建出来的广义圆方树是一种怎样的形态。它一定是圆方点交错的形式。换句话说,一条边若不在点双连通分量内,它就会变成一个方点,并连接其原来的两个点。

    换句话说,我们把一条边转化成了一个点。于是我们就可以像上面处理点一样处理了。

    实现

    判断一个点是否在两点路径上,我们可以用树剖实现。具体来讲,在跳LCA的过程中判断被删点是否在起终点之间,我们用链首和深度判断即可。

    由于题目查询边的给出方式约束,我们可以用 map 实现查询边是否在点双内。代码中,minmax 函数为 C++11 语法,其返回值为一个排好序后的 pair 。

    整体时间复杂度为 (O(n+q(log n+log m)))

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<cmath>
    #include<map>
    using namespace std;
    inline int read(){
    	int w=0,x=0;char c=getchar();
    	while(!isdigit(c))w|=c=='-',c=getchar();
    	while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
    	return w?-x:x;
    }
    namespace star
    {
    	const int maxn=2e5+10,maxm=5e5+10;
    	typedef pair<int,int> pii;
    	int n,m;
    	struct gragh{
    		int ecnt,head[maxn],to[maxm<<1],nxt[maxm<<1];
    		inline void addedge(int a,int b){
    			to[++ecnt]=b,nxt[ecnt]=head[a],head[a]=ecnt;
    			to[++ecnt]=a,nxt[ecnt]=head[b],head[b]=ecnt;
    		}
    	}G1,G2;
    	int tot,cnt,st[maxn],dfn[maxn],low[maxn];
    	map<pii,int> mp;
    	void tarjan(int x,int f){
    		dfn[x]=low[x]=++tot;
    		st[++st[0]]=x;
    		for(int i=G1.head[x];i;i=G1.nxt[i]){
    			int u=G1.to[i];
    			if(u==f)continue;
    			if(!dfn[u]){
    				tarjan(u,x);
    				low[x]=min(low[x],low[u]);
    				if(low[u]>=dfn[x]){
    					cnt++;
    					if(low[u]>dfn[x]) mp.insert(make_pair(minmax(u,x),cnt));
    					G2.addedge(cnt,x);
    					int now=-1;
    					while(now^u)
    						now=st[st[0]--],G2.addedge(now,cnt);
    				}
    			}else low[x]=min(low[x],dfn[u]);
    		}
    	}
    	int fa[maxn],dep[maxn],top[maxn],son[maxn],siz[maxn];
    	void dfs1(int x,int f){
    		fa[x]=f,dep[x]=dep[f]+1;siz[x]=1;
    		for(int i=G2.head[x];i;i=G2.nxt[i]){
    			int u=G2.to[i];
    			if(u==f)continue;
    			dfs1(u,x);
    			siz[x]+=siz[u];
    			if(siz[u]>siz[son[x]])son[x]=u;
    		}
    	}
    	void dfs2(int x,int topf){
    		top[x]=topf;
    		if(!son[x]) return;
    		dfs2(son[x],topf);
    		for(int i=G2.head[x];i;i=G2.nxt[i]){
    			int u=G2.to[i];
    			if(u==fa[x] or u==son[x]) continue;
    			dfs2(u,u);
    		}
    	}
    	inline bool LCA(int x,int y,int z){
    		while(top[x]!=top[y]){
    			if(dep[top[x]]<dep[top[y]])swap(x,y);
    			if(top[x]==top[z] and dep[z]<=dep[x]) return 1;
    			x=fa[top[x]];
    		}
    		if(dep[x]<dep[y])swap(x,y);
    		if(top[x]==top[z] and dep[z]>=dep[y] and dep[z]<=dep[x]) return 1;
    		return 0;
    	}
    	inline void work(){
    		n=cnt=read(),m=read();
    		for(int i=1;i<=m;i++) G1.addedge(read(),read());
    		tarjan(1,0);
    		dfs1(1,0);
    		dfs2(1,1);
    		int Q=read();
    		while(Q--)
    			if(read()==1){
    				int x=read(),y=read();
    				map<pii,int>::iterator it=mp.find(minmax(read(),read()));
    				if(it==mp.end()) puts("yes");
    				else puts(LCA(x,y,(*it).second)?"no":"yes");
    			}else{
    				int x=read(),y=read(),z=read();
    				puts(LCA(x,y,z)?"no":"yes");
    			}
    	}
    }
    signed main(){
    	star::work();
    	return 0;
    }
    
  • 相关阅读:
    UOJ #455 [UER #8]雪灾与外卖 (贪心、模拟费用流)
    Codeforces 482E ELCA (LCT)
    Codeforces 798D Mike and distribution (构造)
    AtCoder AGC017C Snuke and Spells
    HDU 6089 Rikka with Terrorist (线段树)
    HDU 6136 Death Podracing (堆)
    AtCoder AGC032D Rotation Sort (DP)
    jenkins+python+kubectl实现批量更新k8s镜像
    Linux 下载最新kubectl版本的命令:
    jenkins X 和k8s CI/CD
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/13931989.html
Copyright © 2011-2022 走看看