Cod sursa(job #1755099)

Utilizator killer301Ioan Andrei Nicolae killer301 Data 9 septembrie 2016 14:02:49
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.19 kb
#include<stdio.h>
#include<algorithm>
#include<vector>

using namespace std;

#define lg 32002
#define pb push_back

int n, m, x, y, ind, s, nrc, i, j, p1, p2, poz[lg], cmp[lg], euler[2 * lg], init[lg], q[131100], cur, rad, grd[100002], teste, test, lca, cnt[100002], spoz[lg];
bool fst[lg];
vector<int> v[2][lg], w[lg];

inline bool compare(int a, int b){
    return spoz[a] > spoz[b];
}

void df(int nod){
    fst[nod] = 1;

    for (int i = 0; i < (int)v[s][nod].size(); i ++)
        if (!fst[ v[s][nod][i] ])
            df(v[s][nod][i]);

    poz[++ ind] = nod; spoz[nod] = ind;
}
void find(int nod){
    fst[nod] = 0; cmp[nod] = nrc;

    for (int i = 0; i < (int)w[nod].size(); i ++)
        if (fst[ w[nod][i] ])
            find(w[nod][i]);
}

void dfs(int nod, int ad){
    fst[nod] = 0;
    euler[++ cur] = ad; init[nod] = cur; //printf("%d ", nod);

    sort(v[1][nod].begin(), v[1][nod].end(), compare);

    for (int i = 0; i < (int)v[1][nod].size(); i ++)
        if (fst[ v[1][nod][i] ] == 1){
            dfs(v[1][nod][i], ad + 1);

            euler[++ cur] = ad; //printf("%d ", nod);
        }
}

int cstr(int st, int dr, int poz){
    if (st == dr)
        return q[poz] = euler[st];

    int x = (st + dr) / 2;

    return q[poz] = min(cstr(st, x, 2 * poz), cstr(x + 1, dr, 2 * poz + 1));
}
int query(int st, int dr, int poz){
    if (p1 <= st && dr <= p2)
        return q[poz];

    if (p1 > dr || p2 < st)
        return 0x3f3f3f3f;

    int x = (st + dr) / 2;

    return min(query(st, x, 2 * poz), query(x + 1, dr, 2 * poz + 1));
}
void new_tree(int nod){
    fst[nod] = 1;

    for (int i = 0; i < (int)v[1][nod].size(); i ++)
        if (!fst[ v[1][nod][i] ]){
            new_tree(v[1][nod][i]);

            if (euler[ init[ cnt[nod] ] ] > euler[ init[ cnt[ v[1][nod][i] ] ] ] || cnt[nod] == 0)
                cnt[nod] = cnt[ v[1][nod][i] ];
        }

    for (int i = 0; i < (int)w[nod].size(); i ++)
        if (euler[ init[ w[nod][i] ] ] < euler[ init[ cnt[nod] ] ] || cnt[nod] == 0)
            cnt[nod] = w[nod][i];


    if (nod != rad)
        v[0][ cnt[nod] ].pb(nod);
}

void inca_un_dfs(int nod){
    int i;

    fst[nod] = 0;
    q[++ ind] = euler[ init[nod] ];

    for (i = 0; i < (int)v[1][nod].size(); i ++){
        int li = 1, ls = ind, x = ind, gs = -1;

        while (li <= ls){
            x = (li + ls) / 2;
            if (q[x] <= cnt[ v[1][nod][i] ]){
                gs = ind - x;
                li = x + 1;
            }
            else
                ls = x - 1;
        }

        //printf("test %d %d\n", nod, cnt[ v[1][nod][i] ]);
        grd[ v[1][nod][i] ] = gs;

        /*if (nod == 8)
            for (int j = 1; j <= ind; j ++)
                printf("-> %d\n", q[j]);*/
    }

    for (i = 0; i < (int)v[0][nod].size(); i ++)
        if (fst[ v[0][nod][i] ])
            inca_un_dfs(v[0][nod][i]);

    ind --;
}

int main()
{
    freopen("obiective.in", "r", stdin);
    freopen("obiective.out", "w", stdout);

    scanf("%d%d", &n, &m);
    for (i = 1; i <= m; i ++){
        scanf("%d%d", &x, &y);

        v[0][x].pb(y);
        w[y].pb(x);
    }

    for (i = 1; i <= n; i ++)
        if (!fst[i])
            df(i);
    for (i = n; i; i --)
        if (fst[ poz[i] ]){
            nrc ++;
            find(poz[i]);
        }

    //for (i = 1; i <= n; i ++)
    //  printf("%d %d\n", i, cmp[i]);

    for (i = 1; i <= n; i ++){
        vector<int> schimb;
        w[i].swap(schimb);
    }

    for (i = 1; i <= n; i ++)
        for (j = 0; j < (int)v[0][i].size(); j ++){
            x = cmp[i], y = cmp[ v[0][i][j] ];

            if (x != y){
                v[1][x].pb(y);
                grd[y] ++;

                w[y].pb(x);
            }
        }
    for (i = 1; i <= nrc; i ++)
        if (!grd[i]){
            rad = i;
            break;
        }

    for (i = 1; i <= n; i ++){
        vector<int> schimb;
        v[0][i].swap(schimb);
    }

    ind = 0, s = 1;
    df(rad);

    //for (i = ind; i; i --)
    //  printf("%d\n", poz[i]);

    //printf("   %d\n", v[1][1][2]);
    dfs(rad, 0);
    cstr(1, cur, 1);

    //for (i = 1; i <= cur; i ++)
    //  printf("\n-> %d\n", euler[i]);

    new_tree(rad);

    /*for (i = 1; i <= n; i ++)
        for (int j = 0; j < (int)v[0][i].size(); j ++)
            printf("plus %d %d\n", i, v[0][i][j]);*/

    for (i = 1; i <= n; i ++){
        vector<int> schimb;

        v[1][i].swap(schimb);
    }

    //printf("-> %d\n", cnt[10]);

    scanf("%d", &teste);
    for (test = 1; test <= teste; test ++){
        scanf("%d%d", &x, &y);

        x = cmp[x], y = cmp[y];
        if (x == y){
            grd[test] = 0;
            continue;
        }

        p1 = init[x]; p2 = init[y];
        if (p1 > p2)
            swap(p1, p2);

        lca = query(1, cur, 1);

        if (lca == euler[ init[x] ]){
            grd[test] = 0;
            continue;
        }
        cnt[test] = lca;

        v[1][x].pb(test);
    }

    ind = 0;
    inca_un_dfs(rad);

    for (i = 1; i <= teste; i ++)
        printf("%d\n", grd[i]);

    return 0;
}