Cod sursa(job #1369255)

Utilizator dariusdariusMarian Darius dariusdarius Data 2 martie 2015 23:04:32
Problema Obiective Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 4.72 kb
#include <algorithm>
#include <deque>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
const int MAX_N = 32005;
const int MAX_M = 64005;

int x[MAX_M], y[MAX_M];
int ctc_count;
vector<int> initial[MAX_N], trans[MAX_N];
vector<int> graph[MAX_N], upwards[MAX_N];
deque<int> order;
int ctc[MAX_N], father[MAX_N];
bool vis[MAX_N];int height[MAX_N];
int dp[17][MAX_N];
int ancestor[17][MAX_N];

void dfs_plus(int node) {
    ctc[node] = -1;
    for (vector<int> :: iterator it = initial[node].begin(); it != initial[node].end(); ++ it) {
        if (!ctc[*it]) {
            dfs_plus(*it);
        }
    }
    order.push_back(node);
}

void dfs_minus(int node) {
    ctc[node] = ctc_count;
    for (vector<int> :: iterator it = trans[node].begin(); it != trans[node].end(); ++ it) {
        if (ctc[*it] == -1) {
            dfs_minus(*it);
        }
    }
}

void dfs(int node) {
    vis[node] = true;
    for (vector<int> :: iterator it = graph[node].begin(); it != graph[node].end(); ++ it) {
        if (!vis[*it]) {
            dfs(*it);
        }
    }
    order.push_back(node);
}

void dfs_tree(int node, int father) {
    dp[0][node] = node; ancestor[0][node] = father;
    height[node] = height[father] + 1;
    for (vector<int> :: iterator it = upwards[node].begin(); it != upwards[node].end(); ++ it) {
        if (height[*it] < height[dp[0][node]]) {
            dp[0][node] = *it;
        }
    }
    for (vector<int> :: iterator it = graph[node].begin(); it != graph[node].end(); ++ it) {
        if (*it > 0) {
            dfs_tree(*it, node);
            if (height[dp[0][*it]] < height[dp[0][node]]) {
                dp[0][node] = dp[0][*it];
            }
        }
    }
}

int lca(int x, int y) {
    if (height[x] < height[y]) {
        swap(x, y);
    }
    for (int pace = 16; pace >= 0; -- pace) {
        if (height[ancestor[pace][x]] >= height[y]) {
            x = ancestor[pace][x];
        }
    }
    if (x == y) {
        return x;
    }
    for (int pace = 16; pace >= 0; -- pace) {
        if (ancestor[pace][x] != ancestor[pace][y]) {
            x = ancestor[pace][x];
            y = ancestor[pace][y];
        }
    }
    return father[x];
}

int main() {
    ifstream fin("obiective.in");
    ofstream fout("obiective.out");
    int n, m;
    fin >> n >> m;
    for (int i = 1; i <= m; ++ i) {
        fin >> x[i] >> y[i];
        initial[x[i]].push_back(y[i]);
        trans[y[i]].push_back(x[i]);
    }


    ///Build the strongly connected components graph:
    for (int i = 1; i <= n; ++ i) {
        if (!ctc[i]) {
            dfs_plus(i);
        }
    }
    while (!order.empty()) {
        if (ctc[order.back()] == -1) {
            ++ ctc_count;
            dfs_minus(order.back());
        }
        order.pop_back();
    }
    for (int i = 1; i <= m; ++ i) {
        if (ctc[x[i]] != ctc[y[i]]) {
            graph[ctc[x[i]]].push_back(ctc[y[i]]);
        }
    }
    n = ctc_count;
    for (int i = 1; i <= n; ++ i) {
        sort(graph[i].begin(), graph[i].end());
        graph[i].erase(unique(graph[i].begin(), graph[i].end()), graph[i].end());
    }

    ///Build a tree:
    for (int i = 1; i <= n; ++ i) {
        if (!vis[i]) {
            dfs(i);
        }
    }
    int root;
    while (!order.empty()) {
        root = order.front();
        for (vector<int> :: iterator it = graph[order.front()].begin(); it != graph[order.front()].end(); ++ it) {
            if (!father[*it]) {
                father[*it] = order.front();
            }
        }
        order.pop_front();
    }
    for (int i = 1; i <= n; ++ i) {
        for (vector<int> :: iterator it = graph[i].begin(); it != graph[i].end(); ++ it) {
            upwards[*it].push_back(i);
            if (father[*it] != i) {
                *it = -*it;
            }
        }
    }

    ///Build a dynamic table:
    dfs_tree(root, 0);
    for (int i = 1; (1 << i) < n; ++ i) {
        for (int j = 1; j <= n; ++ j) {
            dp[i][j] = dp[i - 1][dp[i - 1][j]];
            ancestor[i][j] = ancestor[i - 1][ancestor[i - 1][j]];
        }
    }

    ///Solve queries:
    int x, y, tests;
    for (fin >> tests; tests; -- tests) {
        fin >> x >> y;
        x = ctc[x]; y = ctc[y];
        int z = lca(x, y);
        if (x == z) {
            fout << "0\n";
        } else {
            int answer = 0;
            for (int pace = 16; pace >= 0; -- pace) {
                if (height[dp[pace][x]] > height[z]) {
                    x = dp[pace][x];
                    answer += (1 << pace);
                }
            }
            fout << answer + 1 << "\n";
        }
    }

    return 0;
}