Cod sursa(job #185954)

Utilizator filipbFilip Cristian Buruiana filipb Data 26 aprilie 2008 14:29:59
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.93 kb
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>

using namespace std;

#define CLEAR(x) memset(x, 0, sizeof(x))
#define NMax 32768

int N, M, uz[NMax], timp[NMax], t, ctc, comp[NMax], rad;
int up[16][NMax], nivel[NMax], lg[NMax], bst;
int get_high[16][NMax], highest[NMax], dep[NMax], t_in[NMax], t_out[NMax];
vector<int> G[NMax], GT[NMax];

int cmp_nodes(const int& a, const int& b)
{ return t_out[a] > t_out[b]; }	

void df1(int nod)
{
	int i, sz, x;

	uz[nod] = 1;
	for (sz = G[nod].size(), i = 0; i < sz; ++i)
		if (!uz[x = G[nod][i]])
			df1(x);
	timp[++t] = nod;
}

void df2(int nod)
{
	int i, sz, x;

	uz[nod] = 1; comp[nod] = ctc;
	for (sz = GT[nod].size(), i = 0; i < sz; ++i)
		if (!uz[x = GT[nod][i]])
			df2(x);
}

int det_root(void)
{
	int i, j, sz;
	
	CLEAR(uz);
	for (i = 1; i <= N; ++i)
		for (sz = GT[i].size(), j = 0; j < sz; ++j)
			uz[GT[i][j]] = 1;
	for (i = 1; i <= N; ++i)
		if (!uz[i])
			return i;				
	return -1; // should never arrive here
}

void df3(int nod)
{
	int i, sz, x;
	
	uz[nod] = 1;
	for (i = 0; ; ++i)
	{
		if (!up[i][ up[i][nod] ]) break;
		up[i+1][nod] = up[i][ up[i][nod] ];
	}
	
	for (sz = GT[nod].size(), i = 0; i < sz; ++i)
		if (!uz[x = GT[nod][i]])
		{
			up[0][x] = nod;
			nivel[x] = nivel[nod] + 1;
			df3(x);
		}
	t_out[nod] = (++t);
}

int LCA(int x, int y)
{
	for (; nivel[x] > nivel[y]; x = up[ lg[nivel[x]-nivel[y]] ][x]);
	for (; nivel[y] > nivel[x]; y = up[ lg[nivel[y]-nivel[x]] ][y]);
	if (x == y) return x;

	int log;
	for (log = lg[nivel[x]]; log >= 0; --log)
		if (up[log][x] != up[log][y])
			x = up[log][x], 
			y = up[log][y];
	if (x != y) x = up[0][x];
	return x;
}

void df4(int nod)
{
	int i, sz, x;

	uz[nod] = 1;
	for (sz = GT[nod].size(), i = 0; i < sz; ++i)
		if (!uz[x = GT[nod][i]])
		{
			df4(x);
			if (nivel[ highest[x] ] < nivel[ highest[nod] ])
				highest[nod] = highest[x];
		}
}

void df5(int nod)
{
	int i, sz, x;
	
	for (i = 0; ; ++i)
	{
		if (!get_high[i][ get_high[i][nod] ]) break;
		get_high[i+1][nod] = get_high[i][ get_high[i][nod] ];
	}
	
	uz[nod] = 1;
	t_in[nod] = (++t);
	for (sz = G[nod].size(), i = 0; i < sz; ++i)
		if (!uz[x = G[nod][i]])
		{
			get_high[0][x] = nod;
			dep[x] = dep[nod] + 1;
			df5(x);
		}
	t_out[nod] = (++t);
}

int stramos(int x, int y)
{ return t_in[x] <= t_in[y] && t_out[y] <= t_out[x]; }

int main(void)
{
	int T, i, j, k, sz, log;
	
	freopen("obiective.in", "r", stdin);
	freopen("obiective.out", "w", stdout);

	scanf("%d %d", &N, &M);
	for (; M; --M)
	{
		scanf("%d %d", &i, &j);
		G[i].push_back(j);
		GT[j].push_back(i);
	}

	for (i = 1; i <= N; ++i)
		if (!uz[i])
			df1(i);	
	CLEAR(uz);
	for (i = N; i; --i)
		if (!uz[j = timp[i]])
		{
			++ctc;
			df2(j);
		}

	for (i = 1; i <= N; ++i)
		GT[i].clear();
	for (i = 1; i <= N; ++i)
		for (sz = G[i].size(), j = 0; j < sz; ++j)
			if (comp[i] != comp[G[i][j]])
				GT[comp[i]].push_back( comp[G[i][j]] );

	N = ctc;
	rad = det_root();
	CLEAR(uz);
	t = 0;
	df3(rad);
	for (i = 2; i< NMax; ++i)
		lg[i] = lg[i/2]+1;
	for (i = 1; i <= N; ++i)
		sort(GT[i].begin(), GT[i].end(), cmp_nodes);
	
	for (i = 1; i <= N; ++i)
		highest[i] = up[0][i];
	df4(rad);			
	
	for (i = 1; i <= N; ++i)
		for (sz = GT[i].size(), j = 0; j < sz; ++j)
			if (up[0][ GT[i][j] ] != i)
			{
				if (nivel[i] < highest[ GT[i][j] ])
					highest[ GT[i][j] ] = i;
			}	
	CLEAR(uz);
	df4(rad);		
	
	for (i = 1; i <= N; ++i)
		G[i].clear();
	for (i = 1; i <= N; ++i)
	{
		if (!highest[i]) continue;
		G[highest[i]].push_back(i);
	}
	t = 0;
	CLEAR(uz);
	CLEAR(t_out);
	df5(rad);

	for (scanf("%d", &T); T; --T)
	{
		scanf("%d %d", &i, &j);
		i = comp[i]; j = comp[j];
		if (i == j) 
		{
			printf("0\n");
			continue;
		}
	
		k = LCA(i, j);
		if (i == k)
		{
			printf("0\n");
			continue;
		}
		
		for (bst = 0, log = lg[dep[i]]; log >= 0; )
		{	
			for (; log >= 0 && stramos(get_high[log][i], k); --log);
			if (log >= 0)
				i = get_high[log][i],
				bst += (1<<log),
                log--;
		}

		printf("%d\n", bst+1);
	}
	
	return 0;		
}