Cod sursa(job #193406)

Utilizator victorsbVictor Rusu victorsb Data 4 iunie 2008 13:40:33
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.63 kb
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

#define Nmax 32768
#define INF 0x3f3f3f3f
#define pb push_back
#define sz(a) (int)((a).size())

int n, m, ct, cnt, niv;
vector<int> lv1[Nmax], lv2[Nmax], lv[Nmax];
int comp[Nmax];
int v[Nmax];
int list[Nmax];
int lvl[Nmax], low[Nmax];
int h[2 * Nmax];
int pos[Nmax];
int ai[4 * Nmax];

void citire()
{
	int i, a, b;

	scanf("%d %d\n", &n, &m);
	for (i = 1; i <= m; ++i)
	{
		scanf("%d %d\n", &a, &b);
		lv1[a].pb(b);
		lv2[b].pb(a);
	}
}

void DF1(int nod)
{
	int i;

	v[nod] = 1;
	for (i = 0; i < sz(lv2[nod]); ++i)
		if (!v[lv2[nod][i]])
			DF1(lv2[nod][i]);

	list[++ct] = nod;
}

void DF2(int nod)
{
	int i;

	comp[nod] = ct;
	for (i = 0; i < sz(lv1[nod]); ++i)
		if (!comp[lv1[nod][i]])
			DF2(lv1[nod][i]);
}

void DF(int nod)
{
	int i;

	v[nod] = 1;
	if (lvl[low[nod]] > lvl[nod]) low[nod] = nod;
    h[++cnt] = lvl[nod];
	pos[nod] = cnt;

	for (i = 0; i < sz(lv[nod]); ++i)
        if (lvl[low[lv[nod][i]]] > lvl[nod]) low[lv[nod][i]] = nod;

	for (i = 0; i < sz(lv[nod]); ++i)
		if (!v[lv[nod][i]])
		{
			lvl[lv[nod][i]] = lvl[nod] + 1;
			DF(lv[nod][i]);
			if (lvl[low[lv[nod][i]]] < lvl[low[nod]]) low[nod] = low[lv[nod][i]];
            h[++cnt] = lvl[nod];
		}
}

void init(int nod, int st, int dr)
{
	if (st == dr)
		ai[nod] = h[st];
	else
	{
		int mij = (st + dr) / 2, fs = nod * 2, fd = nod * 2 + 1;

		init(fs, st, mij);
		init(fd, mij + 1, dr);

		ai[nod] = min(ai[fs], ai[fd]);
	}
}

void query(int nod, int st, int dr, int a, int b)
{
	if (a <= st && dr <= b)
		niv = min(niv, ai[nod]);
	else
	{
		int mij = (st + dr) / 2, fs = nod * 2, fd = nod * 2 + 1;

		if (a <= mij) query(fs, st, mij, a, b);
		if (mij < b) query(fd, mij + 1, dr, a, b);
	}
}

void solve()
{
	int i, j, k, a, b, sol;

	for (i = 1; i <= n; ++i)
		if (!v[i])
			DF1(i);

	reverse(list+1, list+n+1);

	for (ct = 0, i = 1; i <= n; ++i)
		if (!comp[list[i]])
		{
			++ct;
			DF2(list[i]);
		}

	for (i = 1; i <= n; ++i)
		for (j = 0; j < sz(lv1[i]); ++j)
			if (comp[i] != comp[lv1[i][j]])
				lv[comp[i]].pb(comp[lv1[i][j]]);

	for (i = 1; i <= n; ++i)
		sort(lv[i].begin(), lv[i].end());

	memset(low, 0, sizeof(low));
	memset(v, 0, sizeof(v));
	lvl[0] = INF;
	lvl[ct] = 1;

	DF(ct);
	init(1, 1, cnt);

	scanf("%d\n", &k);
	for (i = 1; i <= k; ++i)
	{
		scanf("%d %d\n", &a, &b);
		a = comp[a];
		b = comp[b];

        niv = INF;
		query(1, 1, cnt, min(pos[a], pos[b]), max(pos[a], pos[b]));

		sol = 0;
		while (lvl[a] > niv)
		{
			++sol;
			a = low[a];
		}

		printf("%d\n", sol);
	}
}

int main()
{
	freopen("obiective.in", "r", stdin);
	freopen("obiective.out", "w", stdout);

	citire();
	solve();

	return 0;
}