Pagini recente » Cod sursa (job #2723539) | Cod sursa (job #3272712) | Cod sursa (job #3228760) | Cod sursa (job #2276272) | Cod sursa (job #3255715)
#include <bits/stdc++.h>
#define L 32005
#define S 16
using namespace std;
ifstream fin("obiective.in");
ofstream fout("obiective.out");
int n, m, q;
vector <int> G[L], G_reversed[L], topologicalSorting, ctc[L];
vector <pair <int, int>> edges, specialEdges;
int ctcIndex, nodeCtc[L];
bool vis[L];
map <pair <int, int>, bool> mp;
int inDeg[L], root;
queue <int> Q;
int t[S][L], lev[L], h[L], th[S][L];
void dfs(int node) {
vis[node] = true;
for (auto it : G[node])
if (!vis[it])
dfs(it);
topologicalSorting.push_back(node);
}
void clearVis() {
for (int i = 1; i <= n; i++)
vis[i] = false;
}
void createStrongComponent(int node) {
ctc[ctcIndex].push_back(node);
vis[node] = true;
for (auto it : G_reversed[node])
if (!vis[it])
createStrongComponent(it);
}
void getCTC() {
for (int i = 1; i <= n; i++) {
if (vis[i])
continue;
dfs(i);
}
clearVis();
reverse(topologicalSorting.begin(), topologicalSorting.end());
for (auto it : topologicalSorting) {
if (vis[it])
continue;
createStrongComponent(it);
ctcIndex++;
}
for (int i = 0; i < ctcIndex; i++)
for (auto it : ctc[i])
nodeCtc[it] = i + 1;
}
void generateDAG() {
for (int i = 1; i <= n; i++)
G[i].clear();
n = ctcIndex;
for (auto edge : edges) {
if (nodeCtc[edge.first] != nodeCtc[edge.second] && !mp[{nodeCtc[edge.first], nodeCtc[edge.second]}]) {
mp[{nodeCtc[edge.first], nodeCtc[edge.second]}] = true;
G[nodeCtc[edge.first]].push_back(nodeCtc[edge.second]);
inDeg[nodeCtc[edge.second]]++;
}
}
for (int i = 1; i <= n; i++) {
if (inDeg[i] == 0)
root = i;
}
}
void getSpecialEdges() {
mp.clear();
Q.push(root);
while (!Q.empty()) {
int node = Q.front();
Q.pop();
for (auto it : G[node]) {
inDeg[it]--;
if (inDeg[it] == 0) {
mp[{node, it}] = true;
Q.push(it);
}
}
}
for (int i = 1; i <= n; i++)
for (auto it : G[i])
if (!mp[{i, it}])
specialEdges.push_back({i, it});
for (int i = 1; i <= n; i++)
for (int j = 0; j < (int)G[i].size(); j++)
if (!mp[{i, G[i][j]}])
G[i][j] = i;
}
void dfsT(int node) {
vis[node] = true;
for (auto it : G[node]) {
if (vis[it] == true)
continue;
t[0][it] = node;
lev[it] = lev[node] + 1;
dfsT(it);
}
}
void buildLCA() {
t[0][root] = root;
lev[root] = 1;
clearVis();
dfsT(root);
for (int bit = 1; bit < S; bit++)
for (int i = 1; i <= n; i++)
t[bit][i] = t[bit - 1][t[bit - 1][i]];
}
int getKthParent(int node, int k) {
for (int bit = 0; bit < S; bit++)
if (k & (1 << bit))
node = t[bit][node];
return node;
}
int lca(int x, int y) {
if (lev[x] < lev[y])
swap(x, y);
x = getKthParent(x, lev[x] - lev[y]);
if (x == y)
return x;
for (int bit = S - 1; bit >= 0; bit--)
if (t[bit][x] != t[bit][y]) {
x = t[bit][x];
y = t[bit][y];
}
return t[0][x];
}
void dfsH(int node) {
vis[node] = true;
for (auto it : G[node]) {
if (!vis[it]) {
dfsH(it);
if (lev[h[node]] > lev[h[it]]) {
h[node] = h[it];
}
}
}
}
void buildH() {
for (int i = 1; i <= n; i++)
h[i] = t[0][i];
for (auto it : specialEdges)
h[it.second] = it.first;
clearVis();
dfsH(root);
}
void buildTh() {
for (int i = 1; i <= n; i++)
th[0][i] = h[i];
for (int bit = 1; bit < S; bit++)
for (int i = 1; i <= n; i++)
th[bit][i] = th[bit - 1][th[bit - 1][i]];
}
int countOp(int x, int y) {
if (lev[x] <= lev[y])
return 0;
int op = 0;
for (int bit = S - 1; bit >= 0; bit--) {
if (lev[th[bit][x]] > lev[y]) {
op += (1 << bit);
x = th[bit][x];
}
}
return op + 1;
}
int main() {
fin >> n >> m;
for (int i = 1; i <= m; i++) {
int a, b;
fin >> a >> b;
G[a].push_back(b);
G_reversed[b].push_back(a);
edges.push_back({a, b});
}
getCTC();
generateDAG();
getSpecialEdges();
buildLCA();
buildH();
buildTh();
fin >> q;
for (int i = 1; i <= q; i++) {
int a, b;
fin >> a >> b;
a = nodeCtc[a];
b = nodeCtc[b];
fout << countOp(a, lca(a, b)) << "\n";
}
return 0;
}