Pagini recente » Cod sursa (job #30594) | Cod sursa (job #1060430) | Cod sursa (job #801337) | Cod sursa (job #2390592) | Cod sursa (job #1766295)
#include <bits/stdc++.h>
using namespace std;
const int kMaxN = 35005;
const int kMaxLog = 17;
int n, m, t, nc;
vector <int> graph[kMaxN];
/** Disjoint Forests */
int root[kMaxN];
void startForests() {
srand(time(nullptr));
for (int i = 1; i <= nc; i++) {
root[i] = i;
}
}
int findRoot(const int x) {
if (x == root[x]) {
return x;
}
return (root[x] = findRoot(root[x]));
}
bool mergeSets(const int x, const int y) {
int xr = findRoot(x);
int yr = findRoot(y);
if (xr != yr) {
if (rand() & 1) {
swap(xr, yr);
}
root[xr] = yr;
return true;
}
else {
return false;
}
}
/** END Disjoint Forests */
int dfOrder;
int dfn[kMaxN];
int cid[kMaxN];
bool onStack[kMaxN];
stack <int> sccStack;
vector <int> scc[kMaxN];
vector <int> ctree[kMaxN];
vector <int> cback[kMaxN];
/** Strongly Connected Components and Tree */
int findScc(const int u) {
dfOrder++;
dfn[u] = dfOrder;
int minPtr = dfOrder;
sccStack.push(u);
onStack[u] = true;
for (const int v: graph[u]) {
if (!dfn[v]) {
minPtr = min(minPtr, findScc(v));
}
else if (onStack[v]) {
minPtr = min(minPtr, dfn[v]);
}
}
if (dfn[u] == minPtr) {
int v;
nc++;
do {
v = sccStack.top();
sccStack.pop();
cid[v] = nc;
onStack[v] = false;
scc[nc].push_back(v);
} while (v != u);
}
return minPtr;
}
void topSort() {
for (int i = 1; i < nc - i + 1; i++) {
swap(scc[i], scc[nc - i + 1]);
}
for (int i = 1; i <= n; i++) {
cid[i] = nc - cid[i] + 1;
}
}
void buildSccTree() {
topSort();
startForests();
for (int i = 1; i <= nc; i++) {
set <int> cfound;
for (const int u: scc[i]) {
for (const int v: graph[u]) {
if (i != cid[v]) {
cfound.insert(cid[v]);
}
}
}
for (const int u: cfound) {
if (mergeSets(i, u) == true) {
ctree[i].push_back(u);
}
else {
cback[u].push_back(i);
}
}
}
}
/** END Strongly Connected Components and Tree */
/** Tree Processing */
int depthCompressed[kMaxN];
int anc[kMaxLog][kMaxN];
int depth[kMaxN];
int up[kMaxN];
void getAncestors() {
for (int i = 1; i < kMaxLog; i++) {
for (int j = 1; j <= nc; j++) {
anc[i][j] = anc[i - 1][anc[i - 1][j]];
}
}
}
void getLowpoint(const int u) {
for (const int v: ctree[u]) {
depth[v] = depth[u] + 1;
anc[0][v] = u;
up[v] = u;
getLowpoint(v);
if (depth[up[u]] > depth[up[v]]) {
up[u] = up[v];
}
}
for (const int v: cback[u]) {
if (depth[up[u]] > depth[v]) {
up[u] = v;
}
}
}
int getLca(int x, int y) {
if (depth[x] < depth[y]) {
swap(x, y);
}
int hdif = depth[x] - depth[y];
for (int i = 0; hdif > 0; i++, hdif >>= 1) {
if (hdif & 1) {
y = anc[i][y];
}
}
if (x == y) {
return x;
}
for (int i = kMaxLog - 1; i >= 0; i--) {
if (anc[i][x] != anc[i][y]) {
x = anc[i][x];
y = anc[i][y];
}
}
return anc[0][x];
}
int compressUp(const int x) {
if (depthCompressed[x] > 0) {
return depthCompressed[x];
}
return compressUp(up[x]) + 1;
}
void getCompressedDepth() {
depthCompressed[1] = 1;
for (int i = 2; i <= nc; i++) {
if (!depthCompressed[i]) {
depthCompressed[i] = compressUp(i);
}
}
}
/** END Tree Processing */
/** Complete Preprocessing */
void processGraph() {
findScc(1);
buildSccTree();
}
void processTree() {
depth[1] = 1;
up[1] = 1;
getLowpoint(1);
getAncestors();
getCompressedDepth();
}
void fullPreprocess() {
processGraph();
processTree();
}
/** END Complete Preprocessing */
/** Helper Functions */
int solveQuery(const int x, const int y) {
const int u = getLca(cid[x], cid[y]);
return depthCompressed[cid[x]] - min(depthCompressed[u], depthCompressed[up[u]]) - 1;
}
/** END Helper Functions */
int main() {
freopen("obiective.in", "r", stdin);
freopen("obiective.out", "w", stdout);
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, v;
scanf("%d %d", &u, &v);
graph[u].push_back(v);
}
fullPreprocess();
int q;
for (scanf("%d", &q); q > 0; q--) {
int u, v;
scanf("%d %d", &u, &v);
printf("%d\n", solveQuery(u, v));
}
fclose(stdin);
fclose(stdout);
return 0;
}