Cod sursa(job #934058)

Utilizator okros_alexandruOkros Alexandru okros_alexandru Data 30 martie 2013 14:18:52
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.98 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cstring>
#define lmax 16
#define nmax (1<<15)
#define Vecin(G) G[Nod][i]
using namespace std;

vector <int> G[nmax],Gt[nmax],Gs[nmax],Order;
int N,Q,CTC,Root,order,Component[nmax],Log2[nmax];
int Father[lmax][nmax],Level[nmax],Highest[lmax][nmax];
bool used[nmax];

int Query(int A,int B) {
	
	int Answer=0,Step;
	
	for(Step=Log2[Level[A]]+1;Step>=0;Step--)
		if(Level[Highest[Step][A]] > Level[B]) {
			Answer+=(1<<Step);
			A=Highest[Step][A];
			}
		
	return Answer+1;
	
}
int LCA(int A,int B) {
	
	for(;Level[A]>Level[B];A=Father[Log2[Level[A] - Level[B]]][A]);
	for(;Level[B]>Level[A];B=Father[Log2[Level[B] - Level[A]]][B]);
	
	for(int Step=Log2[Level[A]];Step>=0;Step--)
		if(Father[Step][A]!=Father[Step][B]) {
			A=Father[Step][A];
			B=Father[Step][B];
			}
	
	if(A!=B)
		A=Father[0][A];
	
	return A;
	
}
void DfsHighest(int Nod) {
	
	used[Nod]=true;
	
	for(int i=0;i<Gs[Nod].size();i++)
		if(!used[Vecin(Gs)]) {
			
			DfsHighest(Vecin(Gs));
			
			if(Level[Highest[0][Vecin(Gs)]] < Level[Highest[0][Nod]])
				Highest[0][Nod] = Highest[0][Vecin(Gs)];
			
			}
	
}
void BuildHighest() {
	
	int i,j,Nod;
	
	for(Nod=1;Nod<=CTC;Nod++)
		Highest[0][Nod]=Father[0][Nod];
	
	for(Nod=1;Nod<=CTC;Nod++)
		for(i=0;i<Gs[Nod].size();i++)
			if(Level[Nod]<Level[Highest[0][Vecin(Gs)]])
				Highest[0][Vecin(Gs)]=Nod;
	
	memset(used,0,sizeof(used));
	
	DfsHighest(Root);
	
	for(i=1;i<lmax;i++)
		for(j=1;j<=CTC;j++)
			Highest[i][j] = Highest[i-1][ Highest[i-1][j] ];
	
}
void DfsFather(int Nod) {
	
	used[Nod]=true;
	
	for(int i=0;Father[i][ Father[i][Nod] ];i++)
		Father[i+1][Nod] = Father[i][ Father[i][Nod] ];
	
	for(int i=0;i<Gs[Nod].size();i++)
		if(!used[Vecin(Gs)]) {
			
			Father[0][Vecin(Gs)]=Nod;
			Level[Vecin(Gs)]=Level[Nod]+1;
			DfsFather(Vecin(Gs));
			
			}
		
}
void BuildFather() {
	
	int i;
	
	for(i=2;i<nmax;i++)
		Log2[i]=Log2[i>>1]+1;
	
	memset(used,0,sizeof(used));
	
	DfsFather(Root);
	
}
bool compare(int A,int B) {
	
	return Order[A]>Order[B];
	
}
void SortareTopologica(int Nod) {
	
	used[Nod]=true;
	
	for(int i=0;i<Gs[Nod].size();i++)
		if(!used[Vecin(Gs)])
			SortareTopologica(Vecin(Gs));
	
	Order[Nod]=++order;
	
}
void BuildNewG() {
	
	int i,Nod;
	
	memset(used,0,sizeof(used));
	
	for(Nod=1;Nod<=N;Nod++)
		for(i=0;i<G[Nod].size();i++)
			if(Component[Nod] != Component[Vecin(G)]) {
				Gs[Component[Nod]].push_back(Component[Vecin(G)]);
				used[Component[Vecin(G)]]=true;
				}
			
	for(Nod=1;Nod<=CTC;Nod++)
		if(!used[Nod]) {
			Root=Nod;
			break;
			}
	
	memset(used,0,sizeof(used));
	SortareTopologica(Root);
	
	for(Nod=1;Nod<=CTC;Nod++)
		sort(Gs[Nod].begin(),Gs[Nod].end(),compare);
	
}
void DfsComponent(int Nod) {
	
	Component[Nod]=CTC;
	used[Nod]=true;
	
	for(int i=0;i<Gt[Nod].size();i++)
		if(!used[Vecin(Gt)])
			DfsComponent(Vecin(Gt));
	
}
void SortareTopologicaK(int Nod) {
	
	used[Nod]=true;
	
	for(int i=0;i<G[Nod].size();i++)
		if(!used[Vecin(G)])
			SortareTopologicaK(Vecin(G));
	
	Order.push_back(Nod);
	
}
void Kosaraju() {
	
	int i,Nod;
	
	for(Nod=1;Nod<=N;Nod++)
		if(!used[Nod])
			SortareTopologicaK(Nod);
	
	memset(used,0,sizeof(used));
	reverse(Order.begin(),Order.end());
	
	for(i=CTC=0;i<Order.size();i++)
		if(!used[Nod = Order[i]]) {
			CTC++;
			DfsComponent(Nod);
			}
	
}
void read(ifstream & in) {
	
	int x,y,M;
	
	in>>N>>M;
	
	while(M--) {
		
		in>>x>>y;
		G[x].push_back(y);
		Gt[y].push_back(x);
		
		}
	
	in>>Q;
	
}
int main() {
	
	int A,B,C;
	ifstream in("obiective.in");
	ofstream out("obiective.out");
	
	read(in);
	Kosaraju();
	BuildNewG();
	BuildFather();
	BuildHighest();
	
	while(Q--) {
		
		in>>A>>B;
		
		A=Component[A];
		B=Component[B];
		
		C=LCA(A,B);
		
		if(C==A || A==B)
			out<<"0\n";
		else
			out<<Query(A,C)<<'\n';
		
		}
	
	in.close();
	out.close();
	
	return 0;
	
}