Pagini recente » Cod sursa (job #2636409) | Cod sursa (job #631053) | Cod sursa (job #232519) | Cod sursa (job #1917762) | Cod sursa (job #932035)
Cod sursa(job #932035)
#include <fstream>
#include <cstring>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#define mp make_pair
using namespace std;
vector <int> v[32010], vt[32010];
vector <int>G[32010], GT[32010], Nodes[32010];
int ST[32010], tata[32010], lowest[32010], Euler[800010], rmq[800010][20], Log[800010], Depth[32010], First[32010], Nod[800010], ctc[32010];
int t, n, m, i, x, y, root, nr, k, comp, c, j, a, b, lca, d1, d2;
bool viz[32010];
int level[32010], deg[32010], in[32010], out[32010];
stack <int> S;
bool ancestor(int a, int b)
{
return in[a] <= in[b] and out[a] >= out[b];
}
bool cmp(int a, int b)
{
return ST[a] < ST[b];
}
void SortareTopologica(int x)
{
vector <int> :: iterator it;
if(x == root) level[x] = 1;
viz[x] = 1;
for(it = v[x].begin(); it != v[x].end(); ++it)
if(!viz[*it])
{
level[*it] = level[x] + 1;
SortareTopologica(*it);
}
ST[x] = nr--;
}
void Liniarizare(int x, int level)
{
vector <int> :: iterator it;
Euler[++k] = level;
Depth[x] = level;
First[x] = k;
Nod[k] = x;
for(it = G[x].begin(); it != G[x].end(); ++it)
if(!First[*it])
{
Liniarizare(*it, level+1);
Euler[++k] = level;
Nod[k] = x;
}
}
void GetLowest(int x)
{
vector<int>::iterator it;
viz[x] = 1;
in[x] = ++t;
if(x != root) lowest[x] = tata[x];
for(it = v[x].begin(); it != v[x].end(); ++it)
{
if(!viz[*it])
{
tata[*it] = x;
GetLowest(*it);
}
if(level[lowest[*it]] < level[lowest[x]]) lowest[x] = lowest[*it];
}
out[x] = ++t;
for(it = vt[x].begin(); it != vt[x].end(); ++it)
if(level[*it] < level[lowest[x]]) lowest[x] = *it;
}
void DF_back(int x)
{
vector<int>::iterator it;
Nodes[comp].push_back(x);
ctc[x] = comp;
for(it = GT[x].begin(); it != GT[x].end(); ++it)
if(!ctc[*it]) DF_back(*it);
}
void DF(int x)
{
vector<int>::iterator it;
viz[x] = 1;
for(it = G[x].begin(); it != G[x].end(); ++it)
if(!viz[*it]) DF(*it);
S.push(x);
}
int main()
{
vector <int> :: iterator it, vec;
ifstream fi("obiective.in");
ofstream fo("obiective.out");
fi >> n >> m;
for(i = 1; i <= m; i++)
{
fi >> x >> y;
G[x].push_back(y);
GT[y].push_back(x);
}
for(i = 1; i <= n; i++) if(!viz[i]) DF(i);
while(!S.empty())
{
while(!S.empty() and ctc[S.top()]) S.pop();
if(S.empty()) break;
comp++;
DF_back(S.top());
}
for(i = 1; i <= comp; i++)
for(it = Nodes[i].begin(); it != Nodes[i].end(); ++it)
{
for(vec = G[*it].begin(); vec != G[*it].end(); ++vec)
if(ctc[*vec] != i)
{
deg[ctc[*vec]]++;
v[i].push_back(ctc[*vec]);
}
for(vec = GT[*it].begin(); vec != GT[*it].end(); ++vec)
if(ctc[*vec] != i)
{
vt[i].push_back(ctc[*vec]);
}
}
for(i = 1; i <= comp; i++) if(!deg[i]) root = i;
memset(viz, 0, sizeof(viz));
for(i = 1, nr = comp; i <= comp; i++) if(!viz[i]) SortareTopologica(i);
for(i = 1; i <= comp; i++) sort(v[i].begin(), v[i].end(), cmp);
memset(viz, 0, sizeof(viz));
GetLowest(root);
for(i = 1; i <= n; i++) G[i].clear();
for(i = 1; i <= n; i++) G[lowest[i]].push_back(i);
Liniarizare(root, 1);
for(i = 2; i <= k; i++) Log[i] = Log[i/2] + 1;
for(i = 1; i <= k; i++) rmq[i][0] = i;
for(c = 1; (1<<c) <= k; c++)
{
for(i = 1; i <= k; i++)
{
rmq[i][c] = rmq[i][c-1];
j = i + (1<<(c-1));
if(j <= k and Euler[rmq[j][c-1]] < Euler[rmq[i][c]]) rmq[i][c] = rmq[j][c-1];
}
}
fi >> t;
while(t--)
{
fi >> a >> b;
a = ctc[a]; b = ctc[b];
x = First[a]; y = First[b];
if(x > y) swap(x, y);
c = Log[y - x + 1];
lca = rmq[x][c];
j = y - (1<<c) + 1;
if(Euler[lca] > Euler[rmq[j][c]]) lca = rmq[j][c];
lca = Nod[lca];
d1 = Depth[a] - Depth[lca];
if(ancestor(a, b)) fo << "0\n"; else
fo << d1 << "\n";
}
return 0;
}