Cod sursa(job #1766425)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 27 septembrie 2016 22:12:46
Problema Obiective Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.86 kb
#include <bits/stdc++.h>

using namespace std;

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

int n, m, t, nScc;
bool seen[kMaxN];
int sccId[kMaxN];
int depth[kMaxN];
int up[kMaxLog][kMaxN];
int anc[kMaxLog][kMaxN];
vector <int> graph[kMaxN];
vector <int> grapht[kMaxN];
vector <int> tree[kMaxN];
set <pair <int, int>> seenEdge;
stack <int> kosStack;

void fiKosaraju(const int u) {
    seen[u] = true;
    for (const int v: graph[u]) {
        if (!seen[v]) {
            fiKosaraju(v);
        }
    }
    kosStack.push(u);
}

void seKosaraju(const int u, const int c) {
    seen[u] = false;
    sccId[u] = c;
    for (const int v: grapht[u]) {
        if (seen[v]) {
            seKosaraju(v, c);
        }
    }
}

void findScc() {
    for (int i = 1; i <= n; i++) {
        if (!seen[i]) {
            fiKosaraju(i);
        }
    }
    while (!kosStack.empty()) {
        if (seen[kosStack.top()]) {
            nScc++;
            seKosaraju(kosStack.top(), nScc);
        }
        kosStack.pop();
    }
}

void buildSccTree() {
    for (int i = 1; i <= n; i++) {
        for (const int u: graph[i]) {
            if (sccId[i] != sccId[u] && seenEdge.find(make_pair(sccId[i], sccId[u])) == seenEdge.end()) {
                seenEdge.insert(make_pair(sccId[i], sccId[u]));
                seenEdge.insert(make_pair(sccId[u], sccId[i]));
                tree[sccId[i]].push_back(sccId[u]);
            }
        }
    }
    for (int i = 1; i <= nScc; i++) {
        sort(tree[i].begin(), tree[i].end());
    }
}

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

void dfsUp(const int u) {
    seen[u] = false;
    for (const int v: tree[u]) {
        if (seen[v] == true) {
            dfsUp(v);
            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 d = depth[x] - depth[y];
    for (int i = 0; (1 << i) <= d; i++) {
        if ((d >> i) & 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];
}

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);
        grapht[v].push_back(u);
    }
    
    findScc();
    buildSccTree();
    
    depth[1] = 1;
    anc[0][1] = 1;
    up[0][1] = 1;
    dfsInit(1);
    dfsUp(1);
    getAncestors();

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