Cod sursa(job #2105439)

Utilizator lflorin29Florin Laiu lflorin29 Data 13 ianuarie 2018 11:54:19
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.9 kb
#include <bits/stdc++.h>

using namespace std;

int const N = 32000 + 2;
int n, m, t;
vector<int>G[N], T[N];
int wscc[N], sccind;
bool vis[N];
vector<int>order;
vector<int>sccG[N];
int prv[N];
vector<int>TreeG[N];
int anc[17][N], dep[N];
int best[17][N];
void dfs(int x) {
   vis[x] = 1;
   for(int y : G[x]) if(!vis[y]) dfs(y);
   order.push_back(x);
}
void dfs2(int x) {

   vis[x] = 1;
   wscc[x] = sccind;
   for(int y : T[x])
      if(!vis[y]) dfs2(y);
}
int lca(int x, int y) {
   if(dep[x] < dep[y]) swap(x, y);
   for(int i = 15; i >= 0; --i) if(dep[x] - (1 << i) >= dep[y]) x = anc[i][x];
   if(x == y) return x;
   for(int i = 15; i >= 0; --i) if(anc[i][x] > 0 && anc[i][y] > 0 && anc[i][x] != anc[i][y]) x = anc[i][x], y = anc[i][y];
   return anc[0][x];
}
int qry(int x, int y) {
   int up = lca(x, y);
   if(x == up) return 0;
   int ret = 0;
   for(int i = 15; i >= 0; --i) {
      if(dep[best[i][x]] > dep[up]) {
         ret += 1 << i;
         x = best[i][x];
      }
   }
   return ret + 1;

}

void tdfs(int x) {
   vis[x] = 1;
   for(int y : sccG[x]) {
      if(!vis[y]) {
         TreeG[x].push_back(y);
         dep[y] = dep[x] + 1;
         anc[0][y] = min(anc[0][y], x);
         best[0][y] = min(best[0][y], x);
         tdfs(y);
      } else {
         anc[0][x] = min(anc[0][x], y);
         best[0][x] = min(best[0][x], y);
      }
   }
}
void dfsup(int x) {
   for(int y : TreeG[x]) {
      dfsup(y);
      best[0][x] = min(best[0][x], best[0][y]);
   }
}
void findsccs() {
   for(int i = 1; i <= n; ++i) if(!vis[i]) dfs(i);
   fill(vis + 1, vis + n + 1, 0);
   for(int i = order.size() - 1; i >= 0; --i) {
      if(!vis[order[i]]) {
         ++sccind;
         dfs2(order[i]);
      }
   }
   for(int i = 1; i <= sccind; ++i)
      anc[0][i] = n + 1, best[0][i] = i;
   for(int j = 1; (1 << j) <= sccind; ++j)for(int i = 1; i <= n; ++i)best[j][i] = i;
   for(int i = 1; i <= n; ++i) {
      for(int j : G[i]) {
         if(wscc[i] != wscc[j]) {
            int ci = wscc[i], cj = wscc[j];
            sccG[ci].push_back(cj);
         }
      }
   }
   for(int i = 1; i <= n; ++i)sort(sccG[i].begin(), sccG[i].end());
   fill(vis + 1, vis + n + 1, 0);
   anc[0][1] = 0;
   dep[1] = 1;
   tdfs(1);
   dfsup(1);
   for(int p = 1; (1 << p) <= sccind; ++p) {
      for(int i = 1; i <= sccind; ++i) {
         anc[p][i] = anc[p - 1][anc[p - 1][i]];
         best[p][i] = min(best[p - 1][i], best[p - 1][best[p - 1][i]]);
      }
   }

}


int main() {
   ifstream cin("obiective.in");
   ofstream cout("obiective.out");
   cin >> n >> m;
   for(int i = 1; i <= m; ++i) {
      int x, y;
      cin >> x >> y;
      G[x].push_back(y);
      T[y].push_back(x);
   }
   cin >> t;
   findsccs();
   while(t--) {
      int x, y;
      cin >> x >> y;
      x = wscc[x];
      y = wscc[y];
      cout << qry(x, y) << '\n';
   }

}