Cod sursa(job #193392)

Utilizator pauldbPaul-Dan Baltescu pauldb Data 4 iunie 2008 11:05:00
Problema Obiective Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.51 kb
#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], lev[maxn];
int first[maxn], start[maxn];
int rmq[maxl][maxx], lca[maxl][maxx];
int T[maxx];

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];
			 }
}

void DFS5(int nod)
{
	int i;

	lca[0][++l] = nod;
	start[nod] = l;
	
	for (i=0; i<G[nod]; i++)
	{
		lev[A[nod][i]] = lev[nod] + 1;
		DFS5(A[nod][i]);
		lca[0][++l] = nod;
	}
}

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 LCA2(int x, int y)
{
	int px, py, aux;

	px = start[x];
	py = start[y];
	if (px > py) aux = px, px = py, py = aux;

	aux = T[py-px+1];

	if (lev[lca[aux][px]] < lev[lca[aux][py-(1<<aux)+1]]) return lca[aux][px];
	return lca[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;
	DFS4(R);

	// fac rmq-ul pentru lca-ul in graf
	
	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++) A[i].clear();

	for (i=1; i<=N; i++) 
		if (i != R)
			if (from[i] == i) A[tata[i]].pb(i);
			else A[from[i]].pb(i);

	for (i=1; i<=N; i++) G[i] = A[i].size();

	l = 0;
	DFS5(R);

	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 || lev[lca[j-1][i]]<lev[lca[j-1][i+(1<<(j-1))]]) lca[j][i] = lca[j-1][i];
			else lca[j][i] = lca[j-1][i+(1<<(j-1))];

	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
		y = LCA2(x, y);
		printf("%d\n", lev[x] - lev[y]);
	}

	return 0;
}