Blow up the city
Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 712 Accepted Submission(s): 380
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 1
Sample Output
4 3 2 2
Source
2019 Multi-University Training Contest 3
Recommend
chendu | We have carefully selected several similar problems for you: 6730 6729 6728 6727 6726
题目大意:给出了一个有向无环图,出度为0的点为指挥中心,1e5个查询,每次给出两个点,问
有多少种方案(删除一个点)使得任意一点不能到达指挥中心(可以删除指挥中心)。
解题思路:考虑建立支配树,根据支配树的定义(链上的点都是必经点),我们只需要找到查询点的深度即可,
因为两个点会有重复,而重复的就是lca到虚拟根节点。所以容斥一下就可以了。
这里的虚拟根节点需要将所有的出度为0的点连接起来。
我的代码:
#include<bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
typedef long long ll;
const int N = 2e5+5;
const int sz = 19;
struct node
{
int to,nt;
}g1[N*2];
int tot;
int head[N];
void addedg(int u,int v)
{
++tot;
g1[tot].to=v;
g1[tot].nt=head[u];
head[u]=tot;
}
vector<int>g[N];
int in[N],a[N];
void topsort(int n)
{
queue<int>q;
for(int i=1;i<=n;i++)
if(!in[i])q.push(i);
int cnt=0;
while(!q.empty())
{
int u=q.front();
q.pop();
a[++cnt]=u;
for(int i=0;i<g[u].size();i++)
{
int to=g[u][i];
in[to]--;
if(!in[to])q.push(to);
}
}
}
int dep[N];
int fa[N][sz];
int LCA(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int k=dep[x]-dep[y];
for(int i=0;i<sz;i++)
{
if((k>>i)&1)x=fa[x][i];
}
if(x==y)return x;
for(int i=sz-1;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
void build(int n)
{
for(int i=1;i<=n;i++)
{
int u=a[i];
int _lca=g1[head[u]].to;
for(int j=head[u];j;j=g1[j].nt)
{
int to=g1[j].to;
_lca=LCA(_lca,to);
}
dep[u]=dep[_lca]+1;
fa[u][0]=_lca;
for(int j=1;j<sz;j++)fa[u][j]=fa[fa[u][j-1]][j-1];
}
}
void init(int n)
{
tot=0;
memset(in,0,sizeof(in));
memset(head,0,sizeof(head));
memset(dep,0,sizeof(dep));
for(int i=0;i<=n;i++)
for(int j=0;j<sz;j++)fa[i][j]=0;
for(int i=0;i<=n;i++)g[i].clear();
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
init(n);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[v].pb(u);
addedg(u,v);
in[u]++;
}
topsort(n);
build(n);
int q;scanf("%d",&q);
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",dep[x]+dep[y]-dep[LCA(x,y)]);
}
}
}
标称(写的很漂亮):
#include<bits/stdc++.h>
#define LL long long
#define MEM(x,y) memset(x,y,sizeof(x))
#define MOD(x) ((x)%mod)
#define mod 1000000007
#define pb push_back
#define STREAM_FAST ios::sync_with_stdio(false)
using namespace std;
const int maxn = 2e5 + 7;
int n, m, deg[maxn], rt, a[maxn], dep[maxn], val[maxn];
int f[maxn][20];
vector<int>E[maxn], G[maxn], T[maxn];
void BFS()
{
queue<int>q;
rt = n + 1;
for (int i = 1; i <= n; i++) if (!deg[i]){q.push(i); E[rt].pb(i); G[i].pb(rt);}
int tot = 0;
while (!q.empty())
{
int u = q.front(); q.pop();
a[++tot] = u;
for (int v : E[u]) if ((--deg[v]) == 0) q.push(v);
}
}
int LCA(int x, int y)
{
if (dep[x] > dep[y]) swap(x, y);
for (int i = 19; i >= 0; i--) if (dep[y] > dep[x] && dep[f[y][i]] >= dep[x]) y = f[y][i];
for (int i = 19; i >= 0; i--) if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return x == y ? x : f[x][0];
}
int main()
{
int tt; scanf("%d", &tt);
while (tt--)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n + 1; i++)
{
E[i].clear(); G[i].clear();
T[i].clear();
dep[i] = deg[i] = 0;
}
while (m--)
{
int u, v; scanf("%d%d", &u, &v);
E[v].pb(u); G[u].pb(v); deg[u]++;
}
BFS();
dep[rt] = 1;
for (int i = 1; i <= n; i++)
{
int u = a[i], fa = -1;
for (int v : G[u]) fa = (fa == -1 ? v : LCA(fa, v));
dep[u] = dep[fa] + 1; f[u][0] = fa; T[fa].pb(u);
for (int i = 1; i <= 19; i++) f[u][i] = f[f[u][i - 1]][i - 1];
}
int q; scanf("%d", &q);
while (q--)
{
int u, v; scanf("%d%d", &u, &v);
int lca = LCA(u, v);
printf("%d\n", dep[u] + dep[v] - dep[lca] - 1);
}
}
return 0;
}