Cod sursa(job #2922482)

Utilizator Alex_tz307Lorintz Alexandru Alex_tz307 Data 8 septembrie 2022 17:16:51
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.95 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("obiective.in");
ofstream fout("obiective.out");

const int kN = 1 << 15;
const int kLog = 16;
const int INF = 1e9;
int timer, N, tin[kN], low[kN], ctcIndex[kN], dep[kN], in[kN], out[kN], lg2[kN], anc[kN][kLog], lift[kN][kLog];
vector<int> stk, g[kN], G[kN];
bitset<kN> vis;

void minSelf(int &x, int y) {
  if (y < x) {
    x = y;
  }
}

void dfsCTC(int u) {
  tin[u] = ++timer;
  low[u] = timer;
  stk.emplace_back(u);
  for (int v : g[u]) {
    if (tin[v]) {
      minSelf(low[u], tin[v]);
    } else {
      dfsCTC(v);
      minSelf(low[u], low[v]);
    }
  }
  if (tin[u] == low[u]) {
    N += 1;
    int node;
    do {
      node = stk.back();
      stk.pop_back();
      tin[node] = INF;
      ctcIndex[node] = N;
    } while (node != u);
  }
}

void dfsT(int u, int par) {
  vis[u] = true;
  dep[u] = dep[par] + 1;
  anc[u][0] = par;
  lift[u][0] = par;
  in[u] = ++timer;
  for (int v : G[u]) {
    if (vis[v]) {
      minSelf(lift[v][0], u);
    } else {
      dfsT(v, u);
    }
  }
  out[u] = timer;
}

bool isAnc(int u, int v) {
  return in[u] <= in[v] && out[v] <= out[u];
}

int lca(int u, int v) {
  if (dep[u] < dep[v]) {
    swap(u, v);
  }
  if (isAnc(v, u)) {
    return v;
  }
  for (int i = lg2[dep[v]]; i >= 0; --i) {
    if (anc[v][i] && !isAnc(anc[v][i], u)) {
      v = anc[v][i];
    }
  }
  return anc[v][0];
}

int solve(int v, int d) {
  if (dep[v] <= d) {
    return 0;
  }
  int res = 1;
  for (int i = lg2[dep[v]]; i >= 0; --i) {
    if (dep[lift[v][i]] > d) {
      res += (1 << i);
      v = lift[v][i];
    }
  }
  return res;
}

int main() {
  int n, m;
  fin >> n >> m;
  for (int i = 0; i < m; ++i) {
    int u, v;
    fin >> u >> v;
    g[u].emplace_back(v);
  }
  for (int v = 1; v <= n; ++v) {
    if (!tin[v]) {
      dfsCTC(v);
    }
  }
  for (int v = 1; v <= n; ++v) {
    ctcIndex[v] = N - ctcIndex[v] + 1;
  }
  for (int u = 1; u <= n; ++u) {
    for (int v : g[u]) {
      if (ctcIndex[u] != ctcIndex[v]) {
        G[ctcIndex[u]].emplace_back(ctcIndex[v]);
      }
    }
  }
  for (int v = 1; v <= N; ++v) {
    sort(G[v].begin(), G[v].end());
    G[v].erase(unique(G[v].begin(), G[v].end()), G[v].end());
  }
  timer = 0;
  for (int v = 1; v <= N; ++v) {
    if (!vis[v]) {
      dfsT(v, 0);
    }
  }
  for (int v = N; v > 0; --v) {
    minSelf(lift[anc[v][0]][0], lift[v][0]);
  }
  for (int i = 1; i < kLog; ++i) {
    for (int v = 1; v <= N; ++v) {
      anc[v][i] = anc[anc[v][i - 1]][i - 1];
      lift[v][i] = lift[lift[v][i - 1]][i - 1];
    }
  }
  for (int i = 2; i <= N; ++i) {
    lg2[i] = lg2[i / 2] + 1;
  }
  int q;
  fin >> q;
  for (int i = 0; i < q; ++i) {
    int u, v;
    fin >> u >> v;
    u = ctcIndex[u];
    v = ctcIndex[v];
    int l = lca(u, v);
    fout << solve(u, dep[l]) << '\n';
  }
  fin.close();
  fout.close();
  return 0;
}