Pagini recente » Cod sursa (job #197000) | Cod sursa (job #242201) | Cod sursa (job #242763) | Cod sursa (job #1403812) | Cod sursa (job #193410)
Cod sursa(job #193410)
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
#define maxn 32010
#define maxx 64010
#define pb push_back
#define inf 1000000
#define maxl 17
#define min(a,b) (a < b ? a : b)
int n, m, l, N, R;
vector <int> a[maxn], t[maxn];
int g[maxn], gt[maxn];
int s[maxn], u[maxn];
int comp[maxn];
vector <int> cmp[maxn];
vector <int> A[maxn], B[maxn];
int G[maxn];
int pos[maxn], best[maxn], tata[maxn];
int niv[maxn], from[maxn];
int first[maxn];
int rmq[maxl][maxx];
int T[maxx];
int c[maxl][maxn];
void DFS(int nod)
{
int i;
u[nod] = 1;
for (i=0; i<g[nod]; i++)
if (!u[a[nod][i]]) DFS(a[nod][i]);
s[++l] = nod;
}
void DFS2(int nod)
{
int i;
u[nod] = 2;
comp[nod] = N;
cmp[N].pb(nod);
for (i=0; i<gt[nod]; i++)
if (u[t[nod][i]] == 1) DFS2(t[nod][i]);
}
void DFS3(int nod)
{
int i;
u[nod] = 1;
for (i=0; i<G[nod]; i++)
if (!u[A[nod][i]]) DFS3(A[nod][i]);
s[++l] = nod;
}
int fct(int x, int y)
{
return pos[x] < pos[y];
}
void DFS4(int nod)
{
u[nod] = 1;
best[nod] = niv[nod];
from[nod] = nod;
rmq[0][++l] = nod;
first[nod] = l;
int i;
for (i=0; i<G[nod]; i++)
if (!u[B[nod][i]])
{
niv[B[nod][i]] = niv[nod] + 1;
DFS4(B[nod][i]);
rmq[0][++l] = nod;
if (best[B[nod][i]] < best[nod])
{
best[nod] = best[B[nod][i]];
from[nod] = from[B[nod][i]];
}
}
else if (niv[B[nod][i]] < best[nod])
{
best[nod] = niv[B[nod][i]];
from[nod] = B[nod][i];
}
}
int stramos(int x, int y)
{
int rez = 0, j;
if (niv[x] <= niv[y]) return 0;
for (j=0; 1<<j<=N; j++);
for (j--; j>=0; j--)
if (niv[c[j][x]] > niv[y])
{
rez += 1<<j;
x = c[j][x];
}
return rez + 1;
}
int LCA(int x, int y)
{
int px, py, aux;
px = first[x];
py = first[y];
if (px > py) aux = px, px = py, py = aux;
aux = T[py-px+1];
if (niv[rmq[aux][px]] < niv[rmq[aux][py-(1<<aux)+1]]) return rmq[aux][px];
return rmq[aux][py-(1<<aux)+1];
}
int main()
{
freopen("obiective.in", "r", stdin);
freopen("obiective.out", "w", stdout);
int x, y, i, j, k;
scanf("%d %d ", &n, &m);
for (i=1; i<=m; i++)
{
scanf("%d %d ", &x, &y);
a[x].pb(y);
t[y].pb(x);
}
for (i=1; i<=n; i++)
{
g[i] = a[i].size();
gt[i] = t[i].size();
}
// componente tare conexe
for (i=1; i<=n; i++)
if (!u[i])
{
l = 0;
DFS(i);
for (j=l; j>0; j--)
if (u[s[j]] != 2)
{
N++;
DFS2(s[j]);
}
}
// refac graful
int draw = 0;
memset(u, 0, sizeof(u));
for (i=1; i<=N; i++)
{
x = cmp[i].size();
draw++;
u[i] = draw;
for (j=0; j<x; j++)
for (k=0; k<g[cmp[i][j]]; k++)
if (u[comp[a[cmp[i][j]][k]]] != draw)
{
A[i].pb(comp[a[cmp[i][j]][k]]);
u[comp[a[cmp[i][j]][k]]] = draw;
}
}
for (i=1; i<=N; i++) G[i] = A[i].size();
// sortare topologica
memset(u, 0, sizeof(u));
l = 0;
for (i=1; i<=N; i++)
for (j=0; j<G[i]; j++) u[A[i][j]] = 1;
for (i=1; i<=N; i++)
if (!u[i]) R = i;
memset(u, 0, sizeof(u));
DFS3(R);
for (i=1; i<=N; i++) pos[s[i]] = i;
for (i=1; i<=N; i++) best[i] = inf;
// stabilesc muchiile de inaintare si le intorc
for (i=1; i<=N; i++)
for (j=0; j<G[i]; j++)
if (pos[i] < best[A[i][j]])
{
best[A[i][j]] = pos[i];
tata[A[i][j]] = i;
}
for (i=1; i<=N; i++)
for (j=0; j<G[i]; j++)
if (i != tata[A[i][j]]) B[A[i][j]].pb(i);
else B[i].pb(A[i][j]);
for (i=1; i<=N; i++) G[i] = B[i].size();
// fac noduri critice
memset(u, 0, sizeof(u));
l = 0;
niv[R] = 1;
DFS4(R);
// fac rmq-ul pentru lca-ul in graf
for (i=2; i<=l; i++) T[i] = T[i>>1] + 1;
for (j=1; 1<<j<=l; j++)
for (i=1; i<=l; i++)
if (i+(1<<(j-1))>l || niv[rmq[j-1][i]]<niv[rmq[j-1][i+(1<<(j-1))]]) rmq[j][i] = rmq[j-1][i];
else rmq[j][i] = rmq[j-1][i+(1<<(j-1))];
// fac arborele
for (i=1; i<=N; i++)
if (i != R)
if (from[i] == i) c[0][i] = tata[i];
else c[0][i] = from[i];
for (j=1; 1<<j<=N; j++)
for (i=1; i<=N; i++) c[j][i] = c[j-1][c[j-1][i]];
scanf("%d ", &m);
for (i=1; i<=m; i++)
{
scanf("%d %d ", &x, &y);
x = comp[x];
y = comp[y];
y = LCA(x, y); // lca pe graf
printf("%d\n", stramos(x, y));
}
return 0;
}