Pagini recente » Cod sursa (job #2972298) | Cod sursa (job #3278957) | Cod sursa (job #767053) | Cod sursa (job #3291568) | Cod sursa (job #3255668)
#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;
}