Cod sursa(job #1534104)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 23 noiembrie 2015 12:23:33
Problema Obiective Scor 5
Compilator cpp Status done
Runda prep Marime 2.56 kb
#include <fstream>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

const int NMAX = 32005;

vector <int> graph[NMAX];
vector <int> graph_inv[NMAX];

int _stack[NMAX];
int _stack_size;

bool vis[NMAX];
void dfs_inv (int node) {
    vis[node] = true;
    for (auto it: graph_inv[node])
        if (!vis[it])
            dfs_inv(it);
    _stack[++ _stack_size] = node;
}

int which_scc[NMAX];

void dfs (int node, int scc) {
    vis[node] = true;
    which_scc[node] = scc;

    for (auto it: graph[node])
        if (!vis[it])
            dfs(it, scc);
}

vector <int> new_graph[NMAX];
vector <int> tree_graph[NMAX];

int degs[NMAX];

int h[NMAX];
int fathers[15][NMAX];

void dfs_lca (int node) {
    h[node] = h[fathers[0][node]] + 1;
    for (int i = 1; i < 15; ++ i)
        fathers[i][node] = fathers[i - 1][fathers[i - 1][node]];

    for (auto it: tree_graph[node]) {
        fathers[0][it] = node;
        dfs_lca(it);
    }
}

int lca (int a, int b) {
    if (h[a] > h[b])
        swap(a, b);

    for (int i = 14; i >= 0; -- i)
        if (h[fathers[i][b]] >= h[a])
            b = fathers[i][b];

    if (a == b)
        return a;

    for (int i = 14; i >= 0; -- i)
        if (fathers[i][a] != fathers[i][b]) {
            a = fathers[i][a];
            b = fathers[i][b];
        }

    return fathers[0][a];
}

int main()
{
    ifstream cin("obiective.in");
    ofstream cout("obiective.out");

    int n = 0, m = 0;
    cin >> n >> m;

    int a, b;
    while (m --) {
        cin >> a >> b;

        graph[a].push_back(b);
        graph_inv[b].push_back(a);
    }

    for (int i = 1; i <= n; ++ i)
        if (!vis[i])
            dfs_inv(i);

    memset(vis, 0, sizeof(vis));

    int sccs = 0;
    for (int i = n; i; -- i)
        if (!vis[_stack[i]])
            dfs(_stack[i], ++ sccs);

    for (int i = 1; i <= n; ++ i)
        for (auto it: graph[i])
            if (which_scc[i] != which_scc[it])
                new_graph[which_scc[i]].push_back(which_scc[it]);
    n = sccs;

    //Deschiderea tranzitiva
    for (int i = 1; i <= n; ++ i)
        for (auto it: new_graph[i])
            if (!degs[it]) {
                ++ degs[it];
                tree_graph[i].push_back(it);
            }

    dfs_lca(n);

    int q = 0;
    cin >> q;

    while (q --) {
        cin >> a >> b;
        a = which_scc[a], b = which_scc[b];

        cout << h[a] - h[lca(a, b)] << '\n';
    }

    cin.close();
    cout.close();
    return 0;
}