Pagini recente » Cod sursa (job #1930850) | Cod sursa (job #2224388) | Cod sursa (job #693117) | Cod sursa (job #3261495) | Cod sursa (job #1882268)
#include <bits/stdc++.h>
using namespace std;
const int NMAX = 32010, LOG2NMAX = 18;
int N, M, T;
int dfn[NMAX], lowLink[NMAX];
int level[NMAX], where[NMAX];
int RMQ[LOG2NMAX][2 * NMAX], first[NMAX];
int which[NMAX], vertexOrder[NMAX];
int MSB[NMAX];
int ancestor[LOG2NMAX][NMAX];
bool inStack[NMAX];
vector<int> G[NMAX], GT[NMAX];
vector<vector<int>> scc;
struct Compare {
bool operator()(const int &lhs, const int &rhs) const {
return vertexOrder[lhs] < vertexOrder[rhs];
}
};
stack<int> vertex;
void cacheComponent(int x) {
int nowX;
int pos = scc.size();
vector<int> currScc;
do {
nowX = vertex.top();
vertex.pop();
inStack[nowX] = 0;
currScc.push_back(nowX);
which[nowX] = pos;
} while (nowX != x);
scc.push_back(currScc);
}
int currTime;
void tarjanDFS(int node) {
dfn[node] = lowLink[node] = ++currTime;
vertex.push(node);
inStack[node] = 1;
for (const int &it: G[node]) {
if (!dfn[it]) {
tarjanDFS(it);
lowLink[node] = min(lowLink[node], lowLink[it]);
} else if (inStack[it]) {
lowLink[node] = min(lowLink[node], dfn[it]);
}
}
if (lowLink[node] == dfn[node])
cacheComponent(node);
}
vector<int> GS[NMAX], GST[NMAX];
int degree[NMAX];
void buildSccGraph() {
for (int i = 1; i <= N; ++i)
for (const int &it: G[i])
if (which[i] != which[it]) {
GS[which[i]].push_back(which[it]);
++degree[which[it]];
}
}
void DFS(int node, int currLevel, int father) {
level[node] = currLevel;
lowLink[node] = currLevel;
where[node] = node;
RMQ[0][++RMQ[0][0]] = node;
first[node] = RMQ[0][0];
if (father != -1) {
lowLink[node] = level[father];
where[node] = father;
}
for (const int &it: GS[node]) {
DFS(it, currLevel + 1, node);
if (lowLink[node] > lowLink[it]) {
lowLink[node] = lowLink[it];
where[node] = where[it];
}
RMQ[0][++RMQ[0][0]] = node;
}
for (const int &it: GST[node]) {
if (lowLink[node] > level[it]) {
lowLink[node] = level[it];
where[node] = it;
}
}
}
void computeRMQ() {
for (int i = 1; (1 << i) <= RMQ[0][0]; ++i)
for (int j = 1; j + (1 << i) - 1 <= RMQ[0][0]; ++j)
RMQ[i][j] = level[RMQ[i - 1][j]] < level[RMQ[i - 1][j + (1 << i)]] ? RMQ[i - 1][j] : RMQ[i - 1][j + (1 << i)];
}
int computeLCA(int x, int y) {
if (first[x] > first[y])
swap(x, y);
int lgDist = MSB[first[y] - first[x] + 1];
if (level[RMQ[lgDist][first[x]]] < level[RMQ[lgDist][first[y] - (1 << lgDist) + 1]])
return RMQ[lgDist][first[x]];
return RMQ[lgDist][first[y] - (1 << lgDist) + 1];
}
void levelDFS(int node, int currLevel) {
level[node] = currLevel;
for (const int &it: GT[node])
levelDFS(it, currLevel + 1);
}
int main() {
assert(freopen("obiective.in", "r", stdin));
assert(freopen("obiective.out", "w", stdout));
int i, j;
scanf("%d %d", &N, &M);
while (M--) {
int x, y;
scanf("%d %d", &x, &y);
G[x].push_back(y);
}
for (i = 1; i <= N; ++i)
if (!dfn[i])
tarjanDFS(i);
buildSccGraph();
int pos = 0;
queue<int> Q;
int root = -1;
for (i = 1; i <= N; ++i)
if (degree[i] == 0) {
root = i;
Q.push(i);
vertexOrder[i] = pos++;
break;
}
while (!Q.empty()) {
int now = Q.front();
Q.pop();
for (const int &it: GS[now]) {
--degree[it];
if (degree[it] == 0) {
Q.push(it);
vertexOrder[it] = pos++;
}
}
}
for (i = 0; i < int(scc.size()); ++i) {
sort(GS[i].begin(), GS[i].end(), Compare());
GS[i].erase(unique(GS[i].begin(), GS[i].end()), GS[i].end());
for (const int &it: GS[i])
GST[it].push_back(i);
}
memset(lowLink, 0, sizeof lowLink);
DFS(root, 0, -1);
computeRMQ();
for (i = 2; i <= RMQ[0][0]; ++i)
if ((i & (i - 1)) == 0)
MSB[i] = MSB[i - 1] + 1;
else
MSB[i] = MSB[i - 1];
memset(ancestor, -1, sizeof ancestor);
for (i = 0; i < int(scc.size()); ++i) {
ancestor[0][i] = where[i];
if (where[i] != i)
GT[where[i]].push_back(i);
}
for (i = 1; (1 << i) < int(scc.size()); ++i)
for (j = 0; j < int(scc.size()); ++j)
ancestor[i][j] = ancestor[i - 1][ancestor[i - 1][j]];
levelDFS(root, 0);
scanf("%d", &T);
while (T--) {
int x, y;
scanf("%d %d", &x, &y);
x = which[x];
y = which[y];
int nodeX = x;
int LCA = computeLCA(x, y);
for (i = LOG2NMAX - 1; i >= 0; --i)
if (ancestor[i][nodeX] != -1 && level[ancestor[i][nodeX]] > level[LCA])
nodeX = ancestor[i][nodeX];
if (nodeX != root)
nodeX = ancestor[0][nodeX];
cout << level[x] - level[nodeX] << '\n';
}
return 0;
}