分析
先建一棵圆方树,必经点(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;
}