Pagini recente » Cod sursa (job #347659) | Cod sursa (job #1140871) | Cod sursa (job #493020) | Cod sursa (job #773240) | Cod sursa (job #3225334)
#include<iostream>
#include<vector>
#include<functional>
#include<cassert>
using namespace std;
const int NMAX = 32'002;
vector<int> adjDag[NMAX+1] , adjScc[NMAX+1] , adjSccRev[NMAX+1];
vector<int> adjTree[NMAX+1] , adjDagRev[NMAX+1];
int indeg[NMAX+1];
int component[NMAX+1];
int n, m;
int upLca[20][NMAX+1];
int up[20][NMAX+1];
int root = -1;
vector< vector<int> > scc;
void calcScc ()
{
vector<int> nodes;
vector<int> viz(n+1 , 0);
function<void(int)> dfsStiva = [&] (int nod) -> void {
viz[nod] = 1;
for (auto &to : adjScc[nod]) {
if (!viz[to]) {
dfsStiva(to);
}
}
nodes.push_back(nod);
};
function<void(int)> dfsSCC = [&] (int nod) -> void {
scc.back().push_back(nod);
viz[nod] = 1;
component[nod] = scc.size()-1;
for (auto &to : adjSccRev[nod]) {
if (!viz[to]) {
dfsSCC(to);
}
}
};
for (int i = 1; i <= n; i++)
{
if (!viz[i]) {
dfsStiva(i);
}
}
viz.clear();
viz.resize(n+1 , 0);
while (nodes.size())
{
if (!viz[nodes.back()])
{
scc.push_back({});
dfsSCC(nodes.back());
}
nodes.pop_back();
}
for (int comp = 0; comp < scc.size(); comp++)
{
for (auto &nod : scc[comp])
{
// cout <<nod << " " << component[nod] << '\n';
for (auto &to : adjScc[nod])
{
if (component[nod] != component[to])
{
adjDag[comp].push_back(component[to]);
adjDagRev[component[to]].push_back(comp);
indeg[component[to]]++;
}
}
}
}
for (int c = 0; c < scc.size(); c++)
{
if (indeg[c] == 0) root = c;
}
assert(root != -1);
return;
}
int depth[NMAX+1];
void calcTree ()
{
function<void(int)> dfs = [&] (int nod) -> void {
up[0][nod] = nod;
for (auto &to : adjDag[nod])
{
if (depth[to] < depth[nod]+1) {
depth[to] = depth[nod]+1;
upLca[0][to] = nod;
indeg[to]--;
if (indeg[to] == 0)
dfs(to);
}
}
for (auto &to : adjDagRev[nod])
{
if (depth[to] < depth[up[0][nod]])
{
up[0][nod] = to;
}
}
};
function<void(int)> dfsTree = [&] (int nod) -> void {
for (auto &to : adjTree[nod])
{
dfs(to);
if (depth[up[0][to]] < depth[up[0][nod]]) {
up[0][nod] = up[0][to];
}
}
};
depth[root] = 1;
for (int c = 0; c < scc.size(); c++)
{
if (indeg[c] == 0) dfs(c);
}
up[0][root] = n+1;
upLca[0][root] = n+1;
for (int c = 0; c < scc.size(); c++)
{
adjTree[upLca[0][c]].push_back(c);
}
dfsTree(root);
for (int b = 0; b < 16; b++) {
up[b][n+1] = n+1;
upLca[b][n+1] = n+1;
}
for (int b = 1; b < 16; b++)
{
for (int i = 0; i < scc.size(); i++)
{
upLca[b][i] = upLca[b-1][upLca[b-1][i]];
up[b][i] = up[b-1][up[b-1][i]];
}
}
}
int lca (int x , int y)
{
if (depth[x] < depth[y]) swap(x , y);
int d = depth[x] - depth[y];
for (int b = 15; b >= 0; b--)
{
if ((1 << b) & d)
{
x = upLca[b][x];
}
}
if (x == y) return y;
else {
for (int b = 15; b >= 0; b--)
{
if (upLca[b][x] != upLca[b][y]) {
x = upLca[b][x];
y = upLca[b][y];
}
}
return upLca[0][y];
}
}
int main ()
{
freopen("obiective.in" , "r" , stdin);
freopen("obiective.out" , "w" , stdout);
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int x, y; cin >> x >> y;
adjScc[x].push_back(y);
adjSccRev[y].push_back(x);
}
calcScc();
calcTree();
int t; cin >> t;
while (t--)
{
int x, y; cin >> x >> y;
x = component[x] , y = component[y];
int _lca = lca(x , y);
int cost = 0;
// cout << "!" << _lca << '\n';
for (int b = 15; b >= 0; b--)
{
if (depth[up[b][x]] >= depth[_lca]) {
cost |= (1 << b);
x = up[b][x];
}
}
cout << cost << '\n';
}
return 0;
}