Pagini recente » Cod sursa (job #1679186) | Cod sursa (job #1763199) | Cod sursa (job #1754185) | Cod sursa (job #2102178) | Cod sursa (job #1474152)
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
const int Nmax = 32000;
int N,M,T,SCC = 0,root;
vector<int> Adj[Nmax+1],TAdj[Nmax+1];
bool seen[Nmax+1],come[Nmax+1];
stack<int> KosarajuST;
int comp[Nmax+1];
set<int> G[Nmax+1];
int ST[Nmax+1],K[Nmax+1];
vector<int> Graph[Nmax+1];
int Ancestor[16][Nmax+1],Up[16][Nmax+1],lvl[Nmax+1];
struct Compare
{
inline bool operator()(const int& Rs,const int& Ls)
{
return K[Rs] < K[Ls];
}
};
void Dfs1(int node)
{
seen[node] = 1;
for (vector<int>::iterator it = Adj[node].begin(); it != Adj[node].end(); ++it)
if (!seen[*it])
Dfs1(*it);
KosarajuST.push(node);
}
void Dfs2(int node)
{
comp[node] = SCC;
for (vector<int>::iterator it = TAdj[node].begin(); it != TAdj[node].end(); ++it)
if (!comp[*it])
Dfs2(*it);
}
void Kosaraju()
{
for (int i = 1; i <= N; ++i)
if (!seen[i])
Dfs1(i);
while (!KosarajuST.empty())
{
if (!comp[KosarajuST.top()])
{
++SCC;
Dfs2(KosarajuST.top());
}
KosarajuST.pop();
}
}
void BuildDAG()
{
for (int i = 1; i <= N; ++i)
for (vector<int>::iterator it = Adj[i].begin(); it != Adj[i].end(); ++it)
if(comp[i] != comp[*it])
G[comp[i]].insert(comp[*it]);
}
void Tsort(int node)
{
seen[node] = 1;
for (set<int>::iterator it = G[node].begin(); it != G[node].end(); ++it)
if (!seen[*it])
Tsort(*it);
ST[++ST[0]] = node;
}
void TopologicalSort()
{
memset(seen, 0, sizeof seen);
for (int i = 1; i <= SCC; ++i)
if (!seen[i])
Tsort(i);
root = ST[ST[0]];
for (int i = 1; i <= ST[ST[0]]; ++i)
K[ST[i]] = ST[0] - i + 1;
for (int i = 1; i <= SCC; ++i)
{
Graph[i] = vector<int>(G[i].begin(),G[i].end());
sort(Graph[i].begin(),Graph[i].end(),Compare());
}
}
void BuildTree(int node)
{
for (vector<int>::iterator it = Graph[node].begin(); it != Graph[node].end(); ++it)
{
if (!Ancestor[0][*it])
{
Ancestor[0][*it] = node;
lvl[*it] = lvl[node] + 1;
BuildTree(*it);
}
if (!Up[0][*it] || lvl[Up[0][*it]] > lvl[node])
Up[0][*it] = node;
if(node == root) return;
if (!Up[0][node] || lvl[Up[0][node]] > lvl[Up[0][*it]])
Up[0][node] = Up[0][*it];
}
}
void BuildLCA()
{
for (int i = 1; (1 << i) <= SCC; ++i)
for (int j = 1; j <= SCC; ++j)
{
Ancestor[i][j] = Ancestor[i-1][Ancestor[i-1][j]];
Up[i][j] = Up[i-1][Up[i-1][j]];
}
}
int lca(int x,int y)
{
if(lvl[x] < lvl[y])
swap(x,y);
int logx,logy;
for (logx = 1; 1 << logx < lvl[x]; ++logx);
for (logx = 1; 1 << logy < lvl[y]; ++logy);
for (;lvl[x] != lvl[y]; --logx)
if (lvl[x] - (1 << logx) >= lvl[y])
x = Ancestor[logx][x];
if (x == y) return x;
for (; logy >= 0; --logy)
if (Ancestor[logy][y] != Ancestor[logy][x])
{
y = Ancestor[logy][y];
x = Ancestor[logy][x];
}
return Ancestor[0][x];
}
int Solve(int from,int to)
{
if (lvl[from] <= lvl[to]) return 0;
int log;
for (log = 1; (1 << log) <= lvl[from]; ++log);
--log;
int Ret = 0;
for (; log >= 0; --log)
if (Up[log][from] && lvl[Up[log][from]] > lvl[to])
{
from = Up[log][from];
Ret += 1 << log;
}
return Ret + 1;
}
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 a,b;
scanf("%d%d", &a, &b);
Adj[a].push_back(b);
TAdj[b].push_back(a);
}
Kosaraju();
BuildDAG();
TopologicalSort();
BuildTree(root);
BuildLCA();
scanf("%d",&T);
for (int i = 1; i <= T; ++i)
{
int a,b;
scanf("%d%d", &a, &b);
a = comp[a];
b = comp[b];
int l = lca(a,b);
printf("%d\n", Solve(a,l));
}
}