题意:给定一个n点m边的DAG,将只有入边的点称为周驿东点
q次询问,每次给定a,b两点,询问删去某个点x和其相连的所有边,能使a,b至少其中之一不能到达任何周驿东点的x的个数
n,q<=1e5,m<=2e5
思路:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef pair<int,int> PII; 7 typedef pair<ll,ll> Pll; 8 typedef vector<int> VI; 9 #define N 210000 10 #define M 1100000 11 #define fi first 12 #define se second 13 #define MP make_pair 14 #define pi acos(-1) 15 #define mem(a,b) memset(a,b,sizeof(a)) 16 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 17 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 18 #define lowbit(x) x&(-x) 19 #define Rand (rand()*(1<<16)+rand()) 20 #define id(x) ((x)<=B?(x):m-n/(x)+1) 21 #define ls p<<1 22 #define rs p<<1|1 23 24 const ll MOD=998244353,inv2=(MOD+1)/2; 25 double eps=1e-6; 26 ll INF=1e14; 27 28 vector<int> dom[N],be[N]; 29 int f[N][20],head[N],vet[N],nxt[N],dep[N],ind[N], 30 id[N],semi[N],p[N],pa[N],dfn[N],idom[N],mn[N],tot,cnt; 31 32 int read() 33 { 34 int v=0,f=1; 35 char c=getchar(); 36 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 37 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 38 return v*f; 39 } 40 41 void add(int a,int b) 42 { 43 nxt[++tot]=head[a]; 44 vet[tot]=b; 45 head[a]=tot; 46 } 47 48 void dfs(int u) 49 { 50 dfn[u]=++cnt; id[cnt]=u; 51 int e=head[u]; 52 while(e) 53 { 54 int v=vet[e]; 55 if(!dfn[v]) 56 { 57 dfs(v); 58 pa[dfn[v]]=dfn[u]; 59 } 60 be[dfn[v]].push_back(dfn[u]); 61 e=nxt[e]; 62 } 63 } 64 65 int get(int x) 66 { 67 if(p[x]!=p[p[x]]) 68 { 69 if(semi[mn[x]]>semi[get(p[x])]) mn[x]=get(p[x]); 70 p[x]=p[p[x]]; 71 } 72 return mn[x]; 73 } 74 75 void LT() 76 { 77 per(i,cnt,2) 78 { 79 for(int j:be[i]) semi[i]=min(semi[i],semi[get(j)]); 80 dom[semi[i]].push_back(i); 81 int x=p[i]=pa[i]; 82 for(int y:dom[x]) idom[y]=(semi[get(y)]<x?get(y):x); 83 dom[x].clear(); 84 } 85 rep(i,2,cnt) 86 { 87 if(idom[i]!=semi[i]) idom[i]=idom[idom[i]]; 88 dom[id[idom[i]]].push_back(id[i]); 89 } 90 } 91 92 void getdep(int u,int fa) 93 { 94 rep(i,1,19) f[u][i]=f[f[u][i-1]][i-1]; 95 int e=head[u]; 96 while(e) 97 { 98 int v=vet[e]; 99 if(v!=fa) 100 { 101 f[v][0]=u; 102 dep[v]=dep[u]+1; 103 getdep(v,u); 104 } 105 e=nxt[e]; 106 } 107 } 108 109 int lca(int x,int y) 110 { 111 if(dep[x]<dep[y]) swap(x,y); 112 int d=dep[x]-dep[y]; 113 rep(i,0,19) 114 if((d>>i)&1) x=f[x][i]; 115 per(i,19,0) 116 if(f[x][i]!=f[y][i]) 117 { 118 x=f[x][i]; 119 y=f[y][i]; 120 } 121 if(x==y) return x; 122 return f[x][0]; 123 } 124 125 int main() 126 { 127 //freopen("1.in","r",stdin); 128 //freopen("1.out","w",stdout); 129 int cas=read(); 130 while(cas--) 131 { 132 int n=read(),m=read(); 133 tot=0; 134 rep(i,1,n+1) head[i]=ind[i]=dfn[i]=id[i]=idom[i]=0; 135 rep(i,1,m) 136 { 137 int x=read(),y=read(); 138 add(y,x); 139 ind[x]++; 140 } 141 int root=n+1; 142 rep(i,1,n) 143 if(!ind[i]) add(root,i); 144 rep(i,1,root) 145 { 146 dfn[i]=0; 147 dom[i].clear(); 148 be[i].clear(); 149 p[i]=mn[i]=semi[i]=i; 150 } 151 cnt=0; 152 dfs(root); 153 LT(); 154 tot=0; 155 rep(i,1,root) head[i]=0; 156 rep(i,1,root) 157 if(id[idom[i]]) add(id[idom[i]],id[i]); 158 rep(i,1,root) dep[i]=0; 159 getdep(root,0); 160 int q=read(); 161 while(q--) 162 { 163 int x=read(),y=read(); 164 int t=lca(x,y); 165 printf("%d ",dep[x]+dep[y]-dep[t]); 166 } 167 } 168 169 return 0; 170 }