Cod sursa(job #1896838)

Utilizator cella.florescuCella Florescu cella.florescu Data 28 februarie 2017 22:22:10
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.74 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 32e3;
const int MAXLOG = 17;
const int INF = 2e9;

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;
}