Cod sursa(job #2620310)

Utilizator TonisonIlle Antoniu Nicolae Tonison Data 28 mai 2020 17:56:15
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.95 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 32000;
const int MAXLOG = 17;
const int INF = 2000000000;

vector <int> g[MAXN + 1], gt[MAXN + 1];
set <int> dag[MAXN + 1];
stack <int> srt;
int anc[MAXLOG + 1][MAXN + 1], rmq[MAXLOG + 1][2 * MAXN + 1];
int comptc[MAXN + 1], prim[MAXN + 1], lg[2 * MAXN + 1];
bool seen[MAXN + 1];
int comptc_num, euler_num;

void norm_dfs(int node) {
    seen[node] = true;
    for (auto it : g[node])
        if (seen[it] == false)
            norm_dfs(it);
    srt.push(node);
}

void rev_dfs(int node) {
    seen[node] = false;
    comptc[node] = comptc_num;
    for (auto it : gt[node])
        if (seen[it])
            rev_dfs(it);
}

void euler_traversal(int node) {
    seen[node] = true;
    prim[node] = ++euler_num;
    rmq[0][euler_num] = node;
    for (auto it : dag[node])
        if (seen[it] == 0) {
            euler_traversal(it);
            rmq[0][++euler_num] = node;
            anc[0][node] = min(anc[0][node], anc[0][it]);
        }
}

int low_com_anc(int u, int v) {
    if (prim[u] > prim[v])
        swap(u, v);
    int aux = lg[prim[v] - prim[u]];
    return min(rmq[aux][prim[u]], rmq[aux][prim[v] - (1 << aux) + 1]);
}

int main()
{
    int n, m, x, y, t, lca, ans;
    for (int i = 2; i <= 2 * MAXN; ++i)
        lg[i] = lg[i / 2] + 1;
    ifstream fin("obiective.in");
    fin >> n >> m;
    for (int i = 0; i < m; ++i) {
        fin >> x >> y;
        g[x].push_back(y);
        gt[y].push_back(x);
    }
    for (int i = 1; i <= n; ++i)
        if (seen[i] == false)
            norm_dfs(i);
    while (srt.empty() == 0) {
        if (seen[srt.top()]) {
            ++comptc_num;
            rev_dfs(srt.top());
        }
        srt.pop();
    }
    for (int i = 1; i <= n; ++i)
        anc[0][i] = INF;
    for (int i = 1; i <= n; ++i) {
        x = comptc[i];
        for (auto it : g[i])
            if (x != comptc[it]) {
                y = comptc[it];
                dag[x].insert(y);
                anc[0][y] = min(anc[0][y], x);
            }
    }
    euler_traversal(1);
    for (int i = 1; i <= lg[euler_num]; ++i) {
        for (int j = 1; j <= comptc_num; ++j)
            anc[i][j] = anc[i - 1][anc[i - 1][j]];
        for (int j = 1; j <= euler_num - (1 << i) + 1; ++j)
            rmq[i][j] = min(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]);
    }
    fin >> t;
    ofstream fout("obiective.out");
    for (int i = 0; i < t; ++i) {
        fin >> x >> y;
        x = comptc[x]; y = comptc[y];
        lca = low_com_anc(x, y);
        if (x == lca)
            ans = 0;
        else {
            ans = 1;
            for (int step = lg[comptc_num]; step >= 0; --step)
                if (anc[step][x] > lca) {
                    ans += (1 << step);
                    x = anc[step][x];
                }
        }
        fout << ans << '\n';
    }
    fin.close();
    fout.close();
    return 0;
}