Cod sursa(job #393135)

Utilizator andrei.12Andrei Parvu andrei.12 Data 8 februarie 2010 22:22:58
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.1 kb
#include<stdio.h>
#include<algorithm>
#include<vector>

using namespace std;

#define lg 32002
#define pb push_back

int n, m, x, y, ind, s, nrc, i, j, p1, p2, poz[lg], cmp[lg], euler[2 * lg], init[lg], q[131100], cur, rad, grd[100002], teste, test, lca, cnt[100002];
bool fst[lg];
vector<int> v[2][lg], w[lg];

inline bool compare(int a, int b){
	return poz[a] > poz[b];
}

void df(int nod){
	fst[nod] = 1;

	for (int i = 0; i < (int)v[s][nod].size(); i ++)
		if (!fst[ v[s][nod][i] ])
			df(v[s][nod][i]);

	poz[++ ind] = nod;
}
void find(int nod){
	fst[nod] = 0; cmp[nod] = nrc;

	for (int i = 0; i < (int)w[nod].size(); i ++)
		if (fst[ w[nod][i] ])
			find(w[nod][i]);
}

void dfs(int nod, int ad){
	fst[nod] = 0;
	euler[++ cur] = ad; init[nod] = cur; //printf("%d ", nod);

	sort(v[1][nod].begin(), v[1][nod].end(), compare);

	for (int i = 0; i < (int)v[1][nod].size(); i ++)
		if (fst[ v[1][nod][i] ] == 1){
			dfs(v[1][nod][i], ad + 1);

			euler[++ cur] = ad; //printf("%d ", nod);
		}
}

int cstr(int st, int dr, int poz){
	if (st == dr)
		return q[poz] = euler[st];

	int x = (st + dr) / 2;

	return q[poz] = min(cstr(st, x, 2 * poz), cstr(x + 1, dr, 2 * poz + 1));
}
int query(int st, int dr, int poz){
	if (p1 <= st && dr <= p2)
		return q[poz];

	if (p1 > dr || p2 < st)
		return 0x3f3f3f3f;

	int x = (st + dr) / 2;

	return min(query(st, x, 2 * poz), query(x + 1, dr, 2 * poz + 1));
}
void new_tree(int nod){
	fst[nod] = 1;

	for (int i = 0; i < (int)v[1][nod].size(); i ++)
		if (!fst[ v[1][nod][i] ]){
			new_tree(v[1][nod][i]);

			if (euler[ init[ cnt[nod] ] ] < euler[ init[ cnt[ v[1][nod][i] ] ] ] || cnt[nod] == 0)
				cnt[nod] = cnt[ v[1][nod][i] ];
		}

	for (int i = 0; i < (int)w[nod].size(); i ++)
		if (euler[ init[ w[nod][i] ] ] < euler[ init[ cnt[nod] ] ] || cnt[nod] == 0)
			cnt[nod] = w[nod][i];


	if (nod != rad)
		v[0][ cnt[nod] ].pb(nod);
}

void inca_un_dfs(int nod){
	int i;

	fst[nod] = 0;
	q[++ ind] = euler[ init[nod] ];

	for (i = 0; i < (int)v[1][nod].size(); i ++){
		int li = 1, ls = ind, x = ind, gs = -1;

		while (li <= ls){
			x = (li + ls) / 2;
			if (q[x] <= cnt[ v[1][nod][i] ]){
				gs = ind - x;
				li = x + 1;
			}
			else
				ls = x - 1;
		}

		//printf("test %d %d\n", nod, cnt[ v[1][nod][i] ]);
		grd[ v[1][nod][i] ] = gs;

		/*if (nod == 8)
			for (int j = 1; j <= ind; j ++)
				printf("-> %d\n", q[j]);*/
	}

	for (i = 0; i < (int)v[0][nod].size(); i ++)
		if (fst[ v[0][nod][i] ])
			inca_un_dfs(v[0][nod][i]);

	ind --;
}

int main()
{
	freopen("obiective.in", "rt", stdin);
	freopen("obiective.out", "wt", stdout);

	scanf("%d%d", &n, &m);
	for (i = 1; i <= m; i ++){
		scanf("%d%d", &x, &y);

		v[0][x].pb(y);
		w[y].pb(x);
	}

	for (i = 1; i <= n; i ++)
		if (!fst[i])
			df(i);
	for (i = n; i; i --)
		if (fst[ poz[i] ]){
			nrc ++;
			find(poz[i]);
		}

	//for (i = 1; i <= n; i ++)
	//	printf("%d %d\n", i, cmp[i]);

	for (i = 1; i <= n; i ++){
		vector<int> schimb;
		w[i].swap(schimb);
	}

	for (i = 1; i <= n; i ++)
		for (j = 0; j < (int)v[0][i].size(); j ++){
			x = cmp[i], y = cmp[ v[0][i][j] ];

			if (x != y){
				v[1][x].pb(y);
				grd[y] ++;

				w[y].pb(x);
			}
		}
	for (i = 1; i <= nrc; i ++)
		if (!grd[i]){
			rad = i;
			break;
		}

	for (i = 1; i <= n; i ++){
		vector<int> schimb;
		v[0][i].swap(schimb);
	}

	ind = 0, s = 1;
	df(rad);

	//for (i = ind; i; i --)
	//	printf("%d\n", poz[i]);

	//printf("   %d\n", v[1][3][1]);
	dfs(rad, 0);
	cstr(1, cur, 1);

	//for (i = 1; i <= cur; i ++)
	//	printf("\n-> %d\n", euler[i]);

	new_tree(rad);

	/*for (i = 1; i <= n; i ++)
		for (int j = 0; j < (int)v[0][i].size(); j ++)
			printf("%d %d\n", i, v[0][i][j]);*/

	for (i = 1; i <= n; i ++){
		vector<int> schimb;

		v[1][i].swap(schimb);
	}

	scanf("%d", &teste);
	for (test = 1; test <= teste; test ++){
		scanf("%d%d", &x, &y);

		x = cmp[x], y = cmp[y];
		if (x == y){
			grd[test] = 0;
			continue;
		}

		p1 = init[x]; p2 = init[y];
		if (p1 > p2)
			swap(p1, p2);

		lca = query(1, cur, 1);

		if (lca == euler[ init[x] ]){
			grd[test] = 0;
			continue;
		}
		cnt[test] = lca;

		v[1][x].pb(test);
	}

	ind = 0;
	inca_un_dfs(rad);

	for (i = 1; i <= teste; i ++)
		printf("%d\n", grd[i]);

	return 0;
}