Cod sursa(job #67630)

Utilizator ProstuStefan-Alexandru Filip Prostu Data 25 iunie 2007 12:50:04
Problema Obiective Scor 5
Compilator cpp Status done
Runda preONI 2007, Runda Finala, Clasele 11-12 Marime 3.38 kb
// Ce bine era daca stiam si eu componente biconexe
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

#define PB push_back

const int NMAX = 1 << 15;
const int LOGM = 17;

int N, M, NE, P;
int H[NMAX], T[NMAX], h[NMAX], Pt[NMAX], Gr[NMAX];
int Cod[NMAX], in[NMAX], poz[NMAX];
vector <int> G[NMAX], Gp[NMAX];
int RMQ[LOGM][1 << LOGM];
bool V[NMAX];

void read(void) {
	freopen("obiective.in", "rt", stdin);
	int i, u, v;

	scanf(" %d %d", &N, &M);

	for (i = 0; i < M; ++i) {
		scanf(" %d %d", &u, &v);

		G[u].PB(v);
	}
}

int parinte(const int k) {
	if (k != Pt[k])
		Pt[k] = parinte(Pt[k]);
	
	return Pt[k];
}

void unite(int p1, int p2) {
	p1 = parinte(p1);
	p2 = parinte(p2);

	if (p1 == p2) return;

	if (Gr[p1] > Gr[p2])
		Pt[p2] = p1;
	else
		Pt[p1] = p2;
	
	if (Gr[p1] == Gr[p2]) ++Gr[p2];
}

void DFS(int k) {
	vector <int> :: iterator it;

//	printf("%d\n", k);

	V[k] = true;
	H[k] = h[k];
	T[k] = k;

	for (it = G[k].begin(); it != G[k].end(); ++it) {
//		printf("fiu %d\n", *it);
		if (V[*it] == false) {
			h[*it] = h[k] + 1;
			DFS(*it);
		}
		
		if (H[*it] < H[k])
			H[k] = H[*it], T[k] = T[*it];
	}
}

void DFS2(int k, int p) {
	vector <int> :: iterator it;

	V[k] = true;
//	printf("united %d %d\n", k, p);

	for (it = G[k].begin(); it != G[k].end(); ++it)
		if (V[*it] == false) {
			if (H[*it] != h[p]) {
				Cod[*it] = ++P;
				Gp[Cod[p]].PB(Cod[*it]);
				++in[Cod[*it]];
				DFS2(*it, *it);
			} else {
				unite(*it, Cod[p]);
				DFS2(*it, p);
			}
		} else if (H[*it] != h[p]) {
				++in[Cod[*it]];
				Gp[Cod[p]].PB(Cod[*it]);
		}
}

void DFS3(int k) {
	vector <int> :: iterator it;
//	printf("arbore %d\n", k);

	V[k] = true;

	RMQ[0][++NE] = k;
	poz[k] = NE;

	for (it = Gp[k].begin(); it != Gp[k].end(); ++it) {
//		printf("%d\n", *it);

		if (V[*it] == false) {
			H[*it] = H[k] + 1;
			DFS3(*it);
			RMQ[0][++NE] = k;
		}
	}
}

void make_RMQ(void) {
	int i, j, pas, stp, k;

	for (i = 1; (1 << i) <= NE; ++i) {
		pas = 1 << i; stp = 1 << (i - 1); k = i - 1;
		for (j = 1; j + pas <= 1 + NE; ++j) {
			
			if (H[ RMQ[k][j] ] < H[ RMQ[k][j + stp] ])
				RMQ[i][j] = RMQ[k][j];
			else
				RMQ[i][j] = RMQ[k][j + stp];
		}
	}
		
}

void solve(void) {
	int i, R = 0;

	for (i = 1; i <= N; ++i)
		Pt[i] = i;

	for (i = 1; i <= N; ++i)
		if (V[i] == false)
			DFS(i);

	memset(V, 0x00, sizeof(V));

	for (i = 1; i <= N; ++i)
		if (V[i] == false) {
			Cod[i] = ++P;
			DFS2(i, i);
		}

	for (i = 1; i <= P; ++i)
		if (in[i] == 0) {
			R = i;
			break;
		}

	memset(V, 0x00, sizeof(V));

	H[R] = 0;

	DFS3(R);

	make_RMQ();
}

int LCA(int u, int v) {
	int d, k, p1, p2;

	if (poz[u] < poz[v])
		p1 = poz[u], p2 = poz[v];
	else
		p1 = poz[v], p2 = poz[u];
	
	d = p2 - p1 + 1;

	for (k = 0; 1 << (k + 1) <= d; ++k);

	p2 = p2 - (1 << k) + 1;
	if (H[ RMQ[k][p1] ] < H[ RMQ[k][p2] ])
		return RMQ[k][p1];
	
	return RMQ[k][p2];
}

void answer(void) {
	FILE *fout = fopen("obiective.out", "wt");
	int CNT, i, u, v;

	scanf(" %d", &CNT);

	for (i = 0; i < CNT; ++i) {
		scanf(" %d %d", &u, &v);

		u = Cod[ parinte(u) ];
		v = Cod[ parinte(v) ];

//		printf("answer %d %d LCA = %d\n", u, v, LCA(u, v));

		fprintf(fout, "%d\n", H[u] - H[ LCA(u, v) ]);
	}

	fclose(fout);
}

int main(void) {
//	printf("%d\n", sizeof(H) + sizeof(T) + sizeof(h) + sizeof(Pt) + sizeof(Gr) + sizeof(Cod) + sizeof(in) + sizeof(poz) + sizeof(G) + sizeof (Gp) + sizeof(RMQ) + sizeof(V));

	read();

	solve();

	answer();

	return 0;
}