#圆方树,树链剖分#P4334 [COI2007] Policija

题目


分析

先建一棵圆方树,必经点\(z\)就是满足\(z\)\(x\)\(y\)之间的路径上,
这个直接用树链剖分做,必经边必须要满足不在环上,
那么这个必经边就可以找到一个方点,就可以转换成必经点的问题


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <map>
#define rr register
using namespace std;
const int N=200011; struct node{int y,next;}e[N*5],E[N*5]; map<pair<int,int>,int>uk;
int dfn[N],low[N],stac[N],hs[N],dep[N],nfd[N],fat[N],big[N],et=1,Et=1;
int as[N],siz[N],Top[N],cnt[N],dis[N],tot,TOP,n,ext,m,las,a[N],Q;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline void add(int x,int y){
	e[++et]=(node){y,as[x]},as[x]=et;
	e[++et]=(node){x,as[y]},as[y]=et;
}
inline signed min(int a,int b){return a<b?a:b;}
inline void tarjan(int x,int F){
	dfn[x]=low[x]=++tot,stac[++TOP]=x;
	for (rr int i=hs[x];i;i=E[i].next)
	if (!dfn[E[i].y]){
		tarjan(E[i].y,i^1);
		low[x]=min(low[x],low[E[i].y]);
		if (dfn[x]<=low[E[i].y]){
			cnt[++ext]=2;
			if (dfn[x]<low[E[i].y]){
				rr int X=x,Y=E[i].y;
				if (X>Y) X^=Y,Y^=X,X^=Y;
				uk[make_pair(X,Y)]=ext; 
			}
			for (;stac[TOP]!=E[i].y;--TOP)
			    add(ext,stac[TOP]),++cnt[ext];
			add(ext,stac[TOP--]),add(ext,x);
		}
	}else if (i!=F) low[x]=min(low[x],dfn[E[i].y]);
}
inline void dfs1(int x,int fa){
	dep[x]=dep[fa]+1,fat[x]=fa,
	dis[x]=dis[fa]+(x<=n),siz[x]=1;
	for (rr int i=as[x],SIZ=-1;i;i=e[i].next)
	if (e[i].y!=fa){
		dfs1(e[i].y,x),siz[x]+=siz[e[i].y];
		if (siz[e[i].y]>SIZ) big[x]=e[i].y,SIZ=siz[e[i].y];
	}
}
inline void dfs2(int x,int linp){
	dfn[x]=++tot,nfd[tot]=x,Top[x]=linp;
	if (!big[x]) return; dfs2(big[x],linp);
	for (rr int i=as[x];i;i=e[i].next)
	if (e[i].y!=fat[x]&&e[i].y!=big[x])
	    dfs2(e[i].y,e[i].y);
}
inline bool pass_by(int x,int y,int z){
	for (;Top[x]!=Top[y];x=fat[Top[x]]){
		if (dep[Top[x]]<dep[Top[y]]) x^=y,y^=x,x^=y;
		if (Top[z]==Top[x]&&dep[z]<=dep[x]) return 1;
	}
	if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
	if (Top[y]==Top[z]&&dep[x]<=dep[z]&&dep[z]<=dep[y]) return 1;
	return 0;
}
signed main(){
	ext=n=iut(),m=iut();
	for (rr int i=1;i<=m;++i){
		rr int x=iut(),y=iut();
		E[++Et]=(node){y,hs[x]},hs[x]=Et,
		E[++Et]=(node){x,hs[y]},hs[y]=Et;
	}
	tarjan(1,0),tot=TOP=0,dfs1(1,0),dfs2(1,1);
	for (rr int Q=iut();Q;--Q){
		rr int opt=iut(),x=iut(),y=iut(),z;
		if (opt==1){
			rr int X=iut(),Y=iut();
			if (X>Y) X^=Y,Y^=X,X^=Y;
			z=uk[make_pair(X,Y)];
			if (!z) {puts("yes"); continue;}
		}else z=iut();
		puts(pass_by(x,y,z)?"no":"yes");
	}
	return 0;
}
posted @ 2021-07-07 10:29  lemondinosaur  阅读(85)  评论(0编辑  收藏  举报