2019 Multi-University Training Contest 3 Blow up the city (支配樹)

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章