Problem Description
Country A and B are at war. Country A needs to organize transport teams to deliver supplies toward some command center cities.
In order to ensure the delivery works efficiently, all the roads in country A work only one direction. Therefore, map of country A can be regarded as DAG( Directed Acyclic Graph ). Command center cities only received supplies and not send out supplies.
Intelligence agency of country B is credibly informed that there will be two cities carrying out a critical transporting task in country A.
As long as **any** one of the two cities can not reach a command center city, the mission fails and country B will hold an enormous advantage. Therefore, country B plans to destroy one of the n cities in country A and all the roads directly connected. (If a city carrying out the task is also a command center city, it is possible to destroy the city to make the mission fail)
Now country B has made q hypotheses about the two cities carrying out the critical task.
Calculate the number of plan that makes the mission of country A fail.
Input
The first line contains a integer T (1≤T≤10), denoting the number of test cases.
In each test case, the first line are two integers n,m, denoting the number of cities and roads(1≤n≤100,000,1≤m≤200,000).
Then m lines follow, each with two integers u and v, which means there is a directed road from city u to v (1≤u,v≤n,u≠v).The next line is a integer q, denoting the number of queries (1≤q≤100,000)
And then q lines follow, each with two integers a and b, which means the two cities carrying out the critical task are a and b (1≤a,b≤n,a≠b).
A city is a command center if and only if there is no road from it (its out degree is zero).
Output
For each query output a line with one integer, means the number of plan that makes the mission of country A fail.
Sample Input
2
8 8
1 2
3 4
3 5
4 6
4 7
5 7
6 8
7 8
2
1 3
6 7
3 2
3 1
3 2
2
1 2
3 1Sample Output
4
3
2
2
题意:t 组数据,每组数据给出 n 个点 m 条边构成一个 DAG 图,然后给出 q 组查询,每组询问从点 x 到点 y 之间有多少个点被删掉后,使得这两个点中的任何一个无法到达另一个
思路:支配树的 DAG 图模版题
首先进行反向拓扑,然后按照拓扑序建立支配树
由于某点的支配树上的父亲就是该点在 DAG 中的所有出点在支配树上的 LCA,因此对于询问 query(x,y),结果也就是 x 的深度与 y 的深度的和减去 LCA(x,y) 的深度
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<LL,LL>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL quickModPow(LL a,LL b,LL mod){ LL res=1; a=a%mod; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1;} return res; }
LL getInv(LL a,LL mod){ return quickModPow(a,mod-2,mod); }
LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); }
LL LCM(LL x,LL y){ return x/GCD(x,y)*y; }
const double EPS = 1E-10;
const int MOD = 998244353;
const int N = 400000+5;
const int dx[] = {-1,1,0,0,1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;
int n, m, q;
vector<int> G[N];//原图
vector<int> Gf[N];//反图
int in[N];
int a[N], tot;
int deep[N], dp[N][22];
void topSort() {//对反图进行拓扑排序
queue<int> Q;
for (int i = 1; i <= n; i++)
if (in[i] == 0)
Q.push(i);
while (!Q.empty()) {
a[++tot] = Q.front();
Q.pop();
int now = a[tot];
for (int i = 0; i < Gf[now].size(); i++) {
int to = Gf[now][i];
in[to]--;
if (in[to] == 0)
Q.push(to);
}
}
}
int getLCA(int x, int y) {//获取LCA
if (deep[x] < deep[y])
swap(x, y);
int cnt = deep[x] - deep[y];
for (int i = 0; i < 20; i++)
if ((1 << i) & cnt)
x = dp[x][i];
if (x == y)
return x;
for (int i = 19; i >= 0; i--) {
if (dp[x][i] != dp[y][i]) {
x = dp[x][i];
y = dp[y][i];
}
}
return dp[x][0];
}
void init(){
tot=0;
memset(in,0,sizeof(in));
memset(dp,0,sizeof(dp));
for (int i = 0; i <= n; i++) {
G[i].clear();
Gf[i].clear();
}
}
int query(int x,int y){
return deep[x] + deep[y] - deep[getLCA(x, y)];
}
int main() {
int t;
scanf("%d",&t);
while(t--){
init();
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int x,y;
scanf("%d%d", &x, &y);
G[x].push_back(y);
Gf[y].push_back(x);
in[x]++;
}
topSort();
for (int i = 1; i <= n; i++) {
int x = a[i];
if (G[x].size() == 0) {
G[0].push_back(x);
deep[x] = 1;
continue;
}
int y = G[x][0];
for (int i = 1; i < G[x].size(); i++)
y = getLCA(y, G[x][i]);
deep[x] = deep[y] + 1;
dp[x][0] = y;
for (int i = 1; i < 20; i++)
dp[x][i] = dp[dp[x][i-1]][i-1];
}
scanf("%d",&q);
while(q--) {
int x,y;
scanf("%d%d", &x, &y);
printf("%d\n",query(x,y));
}
}
return 0;
}