Blow up the city
Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 892 Accepted Submission(s): 477
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.
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).
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 1
Sample Output
4 3 2 2
题目大意:
给你一张1e5个点的DAG图,所有出度为0的点为终点 ,1e5次询问,每次询问给你两个点,你可以删除图中任意一点,使得这两个点中至少一个点无法到达终点,输出满足条件的点数。
解法:
在不知道这题是灭绝树之前,想的是Tarjan缩点后求关键点,再新建一个源点和每个终点相连,最后查询两个点到源点路径上有多少关键点,然而敲完后才发现这样并不对T_T,不过已经很接近,就差灭绝树建树了哈哈。
从所有终点开始逆着拓扑,每个点的父亲结点就是他所有父亲的LCA(终点的父亲结点特判为源点),LCA的话动态维护一下,最后答案就是询问的两点和源点之间的路径交,也就是dis(U, T) + dis(V,T)- dis(lca(U,V),T)。
Accepted code
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))
typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 1e5 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }
vector <int> G[N], r[N];
int f[N][25], dep[N];
int dis[N], in[N], n, m;
void Init() {
MEM(f, 0);
for (int i = 1; i <= n; i++) {
G[i].clear(), r[i].clear();
dep[i] = in[i] = 0;
}
}
int LCA(int x, int y) {
if (dep[x] > dep[y])
swap(x, y);
for (int i = 20; i >= 0; i--) {
if (dep[y] - (1 << i) >= dep[x])
y = f[y][i];
}
if (x == y)
return x;
for (int i = 20; i >= 0; i--) {
if (f[x][i] == f[y][i])
continue;
x = f[x][i], y = f[y][i];
}
return f[x][0];
}
void Topsort() {
queue <int> q;
for (int i = 1; i <= n; i++) {
if (!in[i])
q.push(i);
}
while (!q.empty()) {
int u = q.front();
q.pop();
if (r[u].empty()) // 终点特判
f[u][0] = 0;
else {
int lca = r[u][0];
for (auto v : r[u]) // 所有父亲的LCA
lca = LCA(lca, v);
f[u][0] = lca;
}
dep[u] = dep[f[u][0]] + 1; // 动态维护
for (int i = 1; (1 << i) <= dep[u]; i++)
f[u][i] = f[f[u][i - 1]][i - 1];
for (auto v : G[u]) {
in[v]--;
if (!in[v])
q.push(v);
}
G[u].clear();
G[f[u][0]].push_back(u); // 存新图
}
}
int main()
{
int T; cin >> T;
while (T--) {
sc("%d %d", &n, &m);
Init();
for (int i = 0; i < m; i++) {
int u, v;
sc("%d %d", &u, &v);
r[u].push_back(v);
G[v].push_back(u);
in[u]++;
}
Topsort();
int q;
sc("%d", &q);
while (q--) {
int u, v;
sc("%d %d", &u, &v);
int lca = LCA(u, v);
printf("%d\n", dep[u] + dep[v] - dep[lca]);
}
}
return 0; // 改数组大小!!!用pair记得改宏定义!!!
}