Cod sursa(job #1766361)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 27 septembrie 2016 21:19:47
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.29 kb
#include <bits/stdc++.h>

using namespace std;

const int kMaxN = 35005;
const int kMaxLog = 17;

int n, m, t, nScc;
vector <int> graph[kMaxN];

/** Strongly Connected Components and Tree */

int dfOrder;
int dfn[kMaxN];
int sccId[kMaxN];
bool onStack[kMaxN];
stack <int> sccStack;
vector <int> sccComp[kMaxN];
vector <int> sccTree[kMaxN];

int findScc(const int u) {
    dfOrder++;
    dfn[u] = dfOrder;
    int minPtr = dfOrder;
    sccStack.push(u);
    onStack[u] = true;
    for (const int v: graph[u]) {
        if (!dfn[v]) {
            minPtr = min(minPtr, findScc(v));
        }
        else if (onStack[v]) {
            minPtr = min(minPtr, dfn[v]);
        }
    }
    if (dfn[u] == minPtr) {
        nScc++;
        while (sccStack.top() != u) {
            onStack[sccStack.top()] = false;
            sccComp[nScc].push_back(sccStack.top());
            sccId[sccStack.top()] = nScc;
            sccStack.pop();
        }
        sccStack.pop();
        onStack[u] = false;
        sccComp[nScc].push_back(u);
        sccId[u] = nScc;
    }
    return minPtr;
}

void buildSccTree() {
    for (int i = 1; 2 * i <= nScc; i++) {
        swap(sccComp[i], sccComp[nScc - i + 1]);
    }
    for (int i = 1; i <= n; i++) {
        sccId[i] = nScc - sccId[i] + 1;
    }
    for (int i = 1; i <= nScc; i++) {
        for (const int u: sccComp[i]) {
            for (const int v: graph[u]) {
                if (sccId[u] != sccId[v]) {
                    sccTree[i].push_back(sccId[v]);
                }
            }
        }
        sort(sccTree[i].begin(), sccTree[i].end());
        sccTree[i].erase(unique(sccTree[i].begin(), sccTree[i].end()), sccTree[i].end());
    }
}

/** END Strongly Connected Components and Tree */

/** Tree Processing */

int depth[kMaxN];
int up[kMaxLog][kMaxN];
int anc[kMaxLog][kMaxN];
bool seen[kMaxN];

void dfsInit(const int u, const int p) {
    depth[u] = depth[p] + 1;
    anc[0][u] = p;
    up[0][u] = p;
    seen[u] = true;
    for (const int v: sccTree[u]) {
        if (seen[v] == false) {
            dfsInit(v, u);
        }
        else if (depth[up[0][v]] > depth[u]) {
            up[0][v] = u;
        }
    }
}

void dfsUp(const int u, const int p) {
    seen[u] = false;
    for (const int v: sccTree[u]) {
        if (seen[v] == true) {
            dfsUp(v, u);
            if (depth[up[0][u]] > depth[up[0][v]]) {
                up[0][u] = up[0][v];
            }
        }
    }
}

void getAncestors() {
    for (int i = 1; i < kMaxLog; i++) {
        for (int j = 1; j <= nScc; j++) {
            anc[i][j] = anc[i - 1][anc[i - 1][j]];
            up[i][j] = up[i - 1][up[i - 1][j]];
        }
    }
}

int getLca(int x, int y) {
    if (depth[x] < depth[y]) {
        swap(x, y);
    }
    int hdif = depth[x] - depth[y];
    for (int i = 0; hdif > 0; i++, hdif >>= 1) {
        if (hdif & 1) {
            x = anc[i][x];
        }
    }
    if (x == y) {
        return x;
    }
    for (int i = kMaxLog - 1; i >= 0; i--) {
        if (anc[i][x] != anc[i][y]) {
            x = anc[i][x];
            y = anc[i][y];
        }
    }
    return anc[0][x];
}

/** END Tree Processing */

/** Preprocess */

void processGraph() {
    findScc(1);
    buildSccTree();
}

void processTree() {
    dfsInit(1, 0);
    dfsUp(1, 0);
    getAncestors();
}

/** END Preprocess */

int main() {
    freopen("obiective.in", "r", stdin);
    freopen("obiective.out", "w", stdout);
    
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        graph[u].push_back(v);
    }
    
    processGraph();
    processTree();
    
    int q;
    for (scanf("%d", &q); q > 0; q--) {
        int u, v;
        scanf("%d %d", &u, &v);
        u = sccId[u];
        v = sccId[v];
        const int x = getLca(u, v);
        if (u == v || u == x) {
            printf("0\n");
        }
        else {
            int s = 0;
            for (int i = kMaxLog - 1; i >= 0; i--) {
                if (depth[up[i][u]] > depth[x]) {
                    u = up[i][u];
                    s |= 1 << i;
                }
            }
            printf("%d\n", s + 1);
        }
    }
    
    return 0;
}