Pagini recente » Cod sursa (job #2626100) | Cod sursa (job #2494321) | Cod sursa (job #2739083) | Cod sursa (job #3214687) | Cod sursa (job #2755462)
#include <fstream>
#include <vector>
#include <stack>
#include <set>
#include <cstring>
using namespace std;
const int kMaxN = 32005, kMaxLog = 16;
//ifstream f("obiective.in");
//ofstream g("obiective.out");
int nodes;
vector<int> graph[kMaxN], transpose_graph[kMaxN];
stack<int> ksr_st;
bool use[kMaxN];
int ctc_nr, ctc[kMaxN];
set<int> ctc_graph[kMaxN];
int ancestor[kMaxLog][kMaxN];
int lg2[kMaxN << 1];
int rmq[kMaxLog][kMaxN << 1], euler_crt, first[kMaxN];
void KosarajuNormalDFS(int node) {
use[node] = true;
for (int i : graph[node])
if (!use[i])
KosarajuNormalDFS(i);
ksr_st.push(node);
}
void KosarajuTransposeDFS(int node) {
ctc[node] = ctc_nr;
for (int i : transpose_graph[node])
if (!ctc[i])
KosarajuTransposeDFS(i);
}
void Kosaraju() {
for (int i = 1; i <= nodes; ++i)
if (!use[i])
KosarajuNormalDFS(i);
while (!ksr_st.empty()) {
if (!ctc[ksr_st.top()]) {
++ctc_nr;
KosarajuTransposeDFS(ksr_st.top());
}
ksr_st.pop();
}
}
void CTCDFS(int node) {
use[node] = true;
rmq[0][++euler_crt] = node;
first[node] = euler_crt;
for (int i : ctc_graph[node])
if (!use[i]) {
CTCDFS(i);
rmq[0][++euler_crt] = node;
ancestor[0][node] = min(ancestor[0][node], ancestor[0][i]);
}
}
void BuildTree() {
memset(ancestor[0], 0x3f, sizeof ancestor[0]);
for (int i = 1; i <= nodes; ++i) {
int x = ctc[i];
for (int j : graph[i]) {
int y = ctc[j];
if (x != y) {
ctc_graph[x].insert(y);
ancestor[0][y] = min(ancestor[0][y], x);
}
}
}
memset(use, 0, sizeof use);
CTCDFS(1);
for (int i = 2; i <= euler_crt; ++i)
lg2[i] = lg2[i >> 1] + 1;
for (int i = 1; i <= lg2[euler_crt]; ++i) {
for (int j = 1; j <= ctc_nr; ++j)
ancestor[i][j] = ancestor[i - 1][ancestor[i - 1][j]];
for (int j = 1; j <= euler_crt - (1 << i) + 1; ++j)
rmq[i][j] = min(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]);
}
}
int LCA(int x, int y) {
x = first[x];
y = first[y];
if (x > y)
swap(x, y);
int lg = lg2[y - x];
return min(rmq[lg][x], rmq[lg][y - (1 << lg) + 1]);
}
int main(int argc, char** argv) {
ifstream f(argv[1]);
ofstream g(argv[2]);
//Read
int edges;
f >> nodes >> edges;
while (edges--) {
int x, y;
f >> x >> y;
graph[x].push_back(y);
transpose_graph[y].push_back(x);
}
Kosaraju();
BuildTree();
//Solve
int q;
f >> q;
while (q--) {
int x, y, lca, u, ans = 1;
f >> x >> y;
x = ctc[x];
y = ctc[y];
lca = LCA(x, y);
if (x == lca) {
g << "0\n";
continue;
}
u = x;
for (int i = lg2[ctc_nr]; i >= 0; --i)
if (ancestor[i][u] > lca) {
u = ancestor[i][u];
ans += 1 << i;
}
g << ans << "\n";
}
f.close();
g.close();
return 0;
}