Pagini recente » Cod sursa (job #2796395) | Cod sursa (job #2810708) | Cod sursa (job #2318891) | Cod sursa (job #1173677) | Cod sursa (job #1219448)
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;
ifstream F("obiective.in");
ofstream G("obiective.out");
const int N = 100010;
const int debug = 0;
int n,nn,m,mark[N],ord[N],where[N];
int root,ancestor[N],level[N],before[N],after[N],when,dad[N];
set<int> w[N];
vector<int> v[N],vt[N],t[N],stack,tree[N];
int stk[N],str[17][N],dd[N];
void print(int n,vector<int> v[N])
{
if ( !debug ) return;
for (int i=1;i<=n;++i)
{
cerr<<i<<" : ";
for (size_t j=0;j<v[i].size();++j)
cerr<<v[i][j]<<' ';
cerr<<'\n';
}
cerr<<'\n';
}
void dff(int x)
{
mark[x] = 1;
for (size_t i=0;i<v[x].size();++i)
{
int y = v[x][i];
if ( mark[y] == 0 )
dff(y);
}
stack.push_back(x);
}
void dfs(int x,int comp)
{
mark[x] = comp;
for (size_t i=0;i<vt[x].size();++i)
{
int y = vt[x][i];
if ( mark[y] == 0 )
dfs(y,comp);
}
}
void ctc()
{
for (int i=1;i<=n;++i)
if ( mark[i] == 0 )
dff(i);
memset(mark,0,sizeof(mark));
for (;!stack.empty();stack.pop_back())
{
int x = stack.back();
if ( mark[x] == 0 )
dfs(x,++nn);
}
for (int x=1;x<=n;++x)
where[x] = mark[x];
for (int x=1;x<=n;++x)
for (size_t j=0;j<v[x].size();++j)
{
int y = v[x][j];
if ( mark[x] != mark[y] )
w[mark[x]].insert(mark[y]);
}
}
void dft(int x)
{
mark[x] = 1;
for (set<int>::iterator it=w[x].begin();it!=w[x].end();++it)
{
int y = *it;
if ( mark[y] == 0 )
dft(y);
}
stack.push_back(x);
}
bool cmp(int x,int y)
{
return ord[x] < ord[y];
}
void sortt()
{
memset(mark,0,sizeof(mark));
stack.clear();
for (int i=1;i<=nn;++i)
if ( mark[i] == 0 )
dft(i);
int sz = stack.size();
root = stack.back();
for (int i=sz;!stack.empty();stack.pop_back(),--i)
{
int x = stack.back();
ord[x] = sz - i + 1;
}
for (int i=1;i<=nn;++i)
{
for (set<int>::iterator it=w[i].begin();it!=w[i].end();++it)
{
t[i].push_back(*it);
t[*it].push_back(i);
}
sort(t[i].begin(),t[i].end(),cmp);
}
}
void build(int x)
{
mark[x] = 1;
before[x] = ++when;
if ( x != root ) ancestor[x] = dad[x];
for (size_t i=0;i<t[x].size();++i)
{
int y = t[x][i];
if ( mark[y] == 0 )
{
dad[y] = x;
level[y] = level[x]+1;
build(y);
if ( y != root )
if ( level[ancestor[y]] < level[ancestor[x]] )
ancestor[x] = ancestor[y];
}
if ( y != root ) //
if ( level[y] < level[ancestor[y]] )
ancestor[x] = y;
}
after[x] = ++when;
}
void bancestors(int x)
{
stk[++stk[0]] = x;
for (size_t i=0;i<tree[x].size();++i)
{
int y = tree[x][i];
dd[y] = x;
bancestors(y);
}
--stk[0];
for (int i=0;i<=15;++i)
{
if ( stk[0] >= (1<<i) )
str[x][i] = stk[ stk[0] - (1<<i) + 1 ];
else
str[x][i] = root;
}
}
bool anc(int x,int y)
{
return before[x] <= before[y] && after[x] >= after[y];
}
int main()
{
F>>n>>m;
for (int i=1,x,y;i<=m;++i)
{
F>>x>>y;
v[x].push_back(y);
vt[y].push_back(x);
}
ctc();
sortt();
print(nn,t);
memset(mark,0,sizeof(mark));
build(root);
for (int i=1;i<=nn;++i)
if ( ancestor[i] != 0 )
tree[ ancestor[i] ].push_back( i );
print(nn,tree);
bancestors(root);
int tt = 0;
F>>tt;
for (int i=1,x,y;i<=tt;++i)
{
F>>x>>y;
x = where[x];
y = where[y];
if ( anc(x,y) )
G<<"0\n";
else
{
int now = x, steps = 0;
for (int j=15;j>=0;--j)
if ( anc(str[now][j],y) == 0 )
{
now = str[now][j];
steps += (1<<j);
}
now = dd[now];
++steps;
G<<steps<<'\n';
}
}
}