Pagini recente » Cod sursa (job #2826656) | Istoria paginii runda/iconcurs18 | Cod sursa (job #718024) | Cod sursa (job #1004958) | Cod sursa (job #1369255)
#include <algorithm>
#include <deque>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
const int MAX_N = 32005;
const int MAX_M = 64005;
int x[MAX_M], y[MAX_M];
int ctc_count;
vector<int> initial[MAX_N], trans[MAX_N];
vector<int> graph[MAX_N], upwards[MAX_N];
deque<int> order;
int ctc[MAX_N], father[MAX_N];
bool vis[MAX_N];int height[MAX_N];
int dp[17][MAX_N];
int ancestor[17][MAX_N];
void dfs_plus(int node) {
ctc[node] = -1;
for (vector<int> :: iterator it = initial[node].begin(); it != initial[node].end(); ++ it) {
if (!ctc[*it]) {
dfs_plus(*it);
}
}
order.push_back(node);
}
void dfs_minus(int node) {
ctc[node] = ctc_count;
for (vector<int> :: iterator it = trans[node].begin(); it != trans[node].end(); ++ it) {
if (ctc[*it] == -1) {
dfs_minus(*it);
}
}
}
void dfs(int node) {
vis[node] = true;
for (vector<int> :: iterator it = graph[node].begin(); it != graph[node].end(); ++ it) {
if (!vis[*it]) {
dfs(*it);
}
}
order.push_back(node);
}
void dfs_tree(int node, int father) {
dp[0][node] = node; ancestor[0][node] = father;
height[node] = height[father] + 1;
for (vector<int> :: iterator it = upwards[node].begin(); it != upwards[node].end(); ++ it) {
if (height[*it] < height[dp[0][node]]) {
dp[0][node] = *it;
}
}
for (vector<int> :: iterator it = graph[node].begin(); it != graph[node].end(); ++ it) {
if (*it > 0) {
dfs_tree(*it, node);
if (height[dp[0][*it]] < height[dp[0][node]]) {
dp[0][node] = dp[0][*it];
}
}
}
}
int lca(int x, int y) {
if (height[x] < height[y]) {
swap(x, y);
}
for (int pace = 16; pace >= 0; -- pace) {
if (height[ancestor[pace][x]] >= height[y]) {
x = ancestor[pace][x];
}
}
if (x == y) {
return x;
}
for (int pace = 16; pace >= 0; -- pace) {
if (ancestor[pace][x] != ancestor[pace][y]) {
x = ancestor[pace][x];
y = ancestor[pace][y];
}
}
return father[x];
}
int main() {
ifstream fin("obiective.in");
ofstream fout("obiective.out");
int n, m;
fin >> n >> m;
for (int i = 1; i <= m; ++ i) {
fin >> x[i] >> y[i];
initial[x[i]].push_back(y[i]);
trans[y[i]].push_back(x[i]);
}
///Build the strongly connected components graph:
for (int i = 1; i <= n; ++ i) {
if (!ctc[i]) {
dfs_plus(i);
}
}
while (!order.empty()) {
if (ctc[order.back()] == -1) {
++ ctc_count;
dfs_minus(order.back());
}
order.pop_back();
}
for (int i = 1; i <= m; ++ i) {
if (ctc[x[i]] != ctc[y[i]]) {
graph[ctc[x[i]]].push_back(ctc[y[i]]);
}
}
n = ctc_count;
for (int i = 1; i <= n; ++ i) {
sort(graph[i].begin(), graph[i].end());
graph[i].erase(unique(graph[i].begin(), graph[i].end()), graph[i].end());
}
///Build a tree:
for (int i = 1; i <= n; ++ i) {
if (!vis[i]) {
dfs(i);
}
}
int root;
while (!order.empty()) {
root = order.front();
for (vector<int> :: iterator it = graph[order.front()].begin(); it != graph[order.front()].end(); ++ it) {
if (!father[*it]) {
father[*it] = order.front();
}
}
order.pop_front();
}
for (int i = 1; i <= n; ++ i) {
for (vector<int> :: iterator it = graph[i].begin(); it != graph[i].end(); ++ it) {
upwards[*it].push_back(i);
if (father[*it] != i) {
*it = -*it;
}
}
}
///Build a dynamic table:
dfs_tree(root, 0);
for (int i = 1; (1 << i) < n; ++ i) {
for (int j = 1; j <= n; ++ j) {
dp[i][j] = dp[i - 1][dp[i - 1][j]];
ancestor[i][j] = ancestor[i - 1][ancestor[i - 1][j]];
}
}
///Solve queries:
int x, y, tests;
for (fin >> tests; tests; -- tests) {
fin >> x >> y;
x = ctc[x]; y = ctc[y];
int z = lca(x, y);
if (x == z) {
fout << "0\n";
} else {
int answer = 0;
for (int pace = 16; pace >= 0; -- pace) {
if (height[dp[pace][x]] > height[z]) {
x = dp[pace][x];
answer += (1 << pace);
}
}
fout << answer + 1 << "\n";
}
}
return 0;
}