Cod sursa(job #3255668)

Utilizator andreic06Andrei Calota andreic06 Data 11 noiembrie 2024 19:57:13
Problema Obiective Scor 5
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.48 kb
#include <bits/stdc++.h>

using namespace std;
ifstream in ("obiective.in");
ofstream out ("obiective.out");

const int V_MAX = 32000;
const int E_MAX = 64000;
const int Q_MAX = 100e3;

int V, E;
vector<int> graph[1 + V_MAX], graphT[1 + V_MAX];
void readInput (void) {
    in >> V >> E;
    for (int i = 1; i <= E; i ++) {
       int u, v; in >> u >> v;
       graph[u].push_back (v);
       graphT[v].push_back (u);
    }
}

bool visited[1 + V_MAX];
vector<int> pseudo_toposort;
void dfs (int node) {
    visited[node] = true;
    for (int x : graph[node])
       if (!visited[x]) dfs (x);
    pseudo_toposort.push_back (node);
}

int SCC = 0; int scc_of[1 + V_MAX];
void dfsT (int node) {
    scc_of[node] = SCC;
    for (int x : graphT[node])
      if (!scc_of[x]) dfsT (x);
}

vector<int> dag[1 + V_MAX];
map<pair<int, int>, bool> isEdge;
int in_degree[1 + V_MAX];
void get_DAG (void) {
   for (int node = 1; node <= V; node ++) {
      for (int x : graph[node]) {
         if (scc_of[node] != scc_of[x] && !isEdge[{scc_of[node], scc_of[x]}]) {
           dag[scc_of[node]].push_back (scc_of[x]);
           isEdge[{scc_of[node], scc_of[x]}] = true;
         }
      }
   }

   for (int node = 1; node <= SCC; node ++) {
      for (int x : dag[node])
         in_degree[x] ++;
   }

   /**for (int node = 1; node <= SCC; node ++) {
      out << node << " : ";
      for (int x : dag[node]) out << x << " ";
      out << "\n";
   }**/
}

int R; vector<int> tree[1 + V_MAX];
vector<int> back_blue[1 + V_MAX];
void createTree (void) {
    queue<int> q;
    for (int node = 1; node <= SCC; node ++)
       if (in_degree[node] == 0) R = node;

    q.push (R);
    while (!q.empty ()) {
       int node = q.front (); q.pop ();
       for (int x : dag[node]) {
          in_degree[x] --;
          if (in_degree[x] == 0) {
            tree[node].push_back (x);
            q.push (x);
          }
          else
            back_blue[x].push_back (node); /// muchia inversata ca sa fac lifting
       }
    }

    /**for (int node = 1; node <= SCC; node ++) {
       out << node << " : ";
       for (int x : tree[node])
          out << x << " ";
       out << "\n";
    }**/
}

const int LOG_MAX = 16;
int ancestor[1 + LOG_MAX][1 + V_MAX];
int d[1 + V_MAX];
void tree_dfs (int root, int p) {
    ancestor[0][root] = p;
    d[root] = d[p] + 1;
    for (int node : tree[root])
       tree_dfs (node, root);
}

void preCompute (void) {
    for (int e = 1; (1 << e) <= SCC; e ++)
       for (int node = 1; node <= SCC; node ++)
          ancestor[e][node] = ancestor[e - 1][ancestor[e - 1][node]];
}
int getLCA (int x, int y) {
   if (d[x] < d[y]) swap (x, y);
   for (int p = LOG_MAX; p >= 0; p --) {
      if (d[ancestor[p][x]] >= d[y])
        x = ancestor[p][x];
   }
   if (x == y) return x;

   for (int p = LOG_MAX; p >= 0; p --) {
      if (ancestor[p][x] != ancestor[p][y]) {
        x = ancestor[p][x];
        y = ancestor[p][y];
      }
   }
   return ancestor[0][x];
}


int h[1 + LOG_MAX][1 + V_MAX];
void dfs_h (int root) {
   for (int node : back_blue[root])
      if (d[h[0][root]] > d[node])
        h[0][root] = node;
   for (int node : tree[root]) {
      dfs_h (node);
      if (d[h[0][root]] > d[h[0][node]])
        h[0][root] = h[0][node];
   }
}


void compute_h (void) {
   for (int node = 1; node <= SCC; node ++)
      h[0][node] = ancestor[0][node];
   for (int e = 1; (1 << e) <= SCC; e ++) {
      for (int node = 1; node <= SCC; node ++)
         h[e][node] = h[e - 1][h[e - 1][node]];
   }
}

int query (int x, int y) {
    x = scc_of[x], y = scc_of[y];

    int lca = getLCA (x, y);

    int answer = 0;
    for (int e = LOG_MAX; e >= 0; e --) {
       if (d[h[e][x]] > d[lca]) {
         x = h[e][x];
         answer += (1 << e);
       }
    }
    return answer + (x != lca);
}

int main()
{
   readInput ();
   for (int node = 1; node <= V; node ++)
      if (!visited[node]) dfs (node);
   reverse (pseudo_toposort.begin (), pseudo_toposort.end ());
   for (int node : pseudo_toposort) {
      if (!scc_of[node]) {
        SCC ++;
        dfsT (node);
      }
   }
   get_DAG ();
   createTree ();
   tree_dfs (R, 0);
   preCompute ();

   ///out << R << endl;

   ///out << getLCA (3, 4);
   dfs_h (R);
   compute_h ();

    int q; in >> q;
    for (int i = 1; i <= q; i ++) {
       int u, v;in >> u >> v;
       out << query (u, v) << "\n";
    }
    return 0;
}