Cod sursa(job #3273336)

Utilizator AlexPlesescuAlexPlesescu AlexPlesescu Data 1 februarie 2025 18:07:09
Problema Obiective Scor 5
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.99 kb
#include <bits/stdc++.h>
#include <unordered_map>

using namespace std;
#define pb push_back
#define sz(x) (int)(x.size())
#define all(a) a.begin(), a.end()
#define nl '\n'
const int N = 32005, INF = 1e9, mod = 998244353;

int n, m, timer, ctc, root_DAG, tin[N], tout[N], depth[N], indeg[N], root[N], up[N][25];
bool used[N];
stack<int> stk;
unordered_map<int, int> mp;
vector<int> g[N], gt[N], dag[N], scc[N];

void dfs1(int node) {
    used[node] = 1;
    for (auto it : g[node]) {
        if (!used[it]) {
            dfs1(it);
        }
    }
    stk.push(node);
}

void dfs2(int node) {
    used[node] = 1;
    scc[ctc].pb(node);
    mp[node] = ctc;
    for (auto it : gt[node]) {
        if (!used[it]) {
            dfs2(it);
        }
    }
}

void dfs(int node, int p = root_DAG) { /// dfs u in arborele ctc urilor
    up[node][0] = p;
    tin[node] = ++timer;
    if (node != root_DAG)
        depth[node] = depth[p] + 1;
    for (int i = 1; i <= 20; i++) {
        up[node][i] = up[up[node][i - 1]][i - 1];
    }
    for (auto it : dag[node]) {
        if (it != p) {
            dfs(it, node);
        }
    }
    tout[node] = ++timer;
}

inline bool is_ancestor(int a, int b) {
    return tin[a] <= tin[b] && tout[a] >= tout[b];
}

int lca(int a, int b) {
    if (is_ancestor(a, b))
        return a;
    if (is_ancestor(b, a))
        return b;
    int u = a;
    for (int i = 20; i >= 0; i--) {
        if (!is_ancestor(up[u][i], b)) {
            u = up[u][i];
        }
    }
    return up[u][0];
}

void run_case(int test_case) {
    int u, v;
    cin >> u >> v;
    int gara = mp[u], muzeu = mp[v];
    cout << depth[gara] - depth[lca(gara, muzeu)] << '\n';
};

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    freopen("obiective.in", "r", stdin);
    freopen("obiective.out", "w", stdout);
    int T = 1;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v;
        cin >> u >> v;
        g[u].pb(v);
        gt[v].pb(u);
    }
    cin >> T;
    dfs1(1);
    for (int i = 1; i <= n; i++) {
        used[i] = 0;
    }
    while (!stk.empty()) {
        int node = stk.top();
        stk.pop();
        if (!used[node]) {
            ++ctc;
            dfs2(node);
            for (auto it : scc[ctc]) {
                root[it] = ctc;
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        for (auto it : g[i]) {
            if (root[it] != root[i]) {
                dag[root[i]].pb(root[it]);
                indeg[root[it]]++;
            }
        }
    }
    root_DAG = 1;
    for (int i = 1; i <= ctc; i++) {
        if (!indeg[i]) {
            root_DAG = i;
            break; /// exista numa una conform exista drum intre oricare 3
        }
    }
    dfs(root_DAG);
    for (int t = 1; t <= T; ++t) {
#ifdef _DEBUG
        cerr << "=== Subtask " << t << " ===" << '\n';
#endif
        run_case(t);
#ifdef _DEBUG
        cerr << nl;
#endif
    }
}