Cod sursa(job #809061)

Utilizator mihaipopa12Popa Mihai mihaipopa12 Data 7 noiembrie 2012 20:29:33
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.61 kb
#include<stdio.h>
#include<vector>
#include<algorithm>

#define maxn 32005
#define maxlog 17
#define pb push_back

using namespace std;

FILE*f=fopen("obiective.in","r");
FILE*g=fopen("obiective.out","w");

int n,m,Ncomp,R,index;
int viz[maxn],st[maxn],comp[maxn],last[maxn],gr_in[maxn],up[maxn],NIV[maxn],NIV_arb[maxn],P[maxlog][maxn],first[maxn];
vector<int>W[maxn],Wt[maxn],C[maxn],G[maxn],Gt[maxn],V[maxn];

inline void citire () {

	fscanf(f,"%d %d",&n,&m);
	int x,y;
	for ( int i = 1 ; i <= m ; ++i ){
		fscanf(f,"%d %d",&x,&y);
		W[x].pb(y); Wt[y].pb(x);
	}
}

void kosaraju1 ( int nod ){
	
	viz[nod] = 1;
	for ( vector<int>::iterator itt = W[nod].begin() ; itt != W[nod].end() ; ++itt ){
		int vecin = (*itt);
		if ( !viz[vecin] ){
			kosaraju1(vecin);
		}
	}
	st[++st[0]] = nod;
}

void kosaraju2 ( int nod ){

	viz[nod] = 0;
	comp[nod] = Ncomp; C[Ncomp].pb(nod);
	for ( vector<int>::iterator itt = Wt[nod].begin() ; itt != Wt[nod].end() ; ++itt ){
		int vecin = (*itt);
		if ( viz[vecin] ){
			kosaraju2(vecin);
		}
	}
}

inline void CTC () {

	for ( int i = 1 ; i <= n ; ++i ){
		kosaraju1(1);
	}
	
	for ( int i = n ; i >= 1 ; --i ){
		if ( viz[ st[i] ] ){
			++Ncomp;
			kosaraju2(st[i]);
		}
	}
}

inline void build_CTC_graph () {
	
	for ( int c = 1 ; c <= Ncomp ; ++c ){
		
		last[c] = c;
		for ( vector<int>::iterator itt = C[c].begin() ; itt != C[c].end() ; ++itt ){
			int nod = (*itt);
			for ( vector<int>::iterator itt_edges = W[nod].begin() ; itt_edges != W[nod].end() ; ++itt_edges ){
				int next_comp = comp[*itt_edges];
				if ( last[next_comp] != c ){
					last[next_comp] = c;
					G[c].pb(next_comp); Gt[next_comp].pb(c);
					++gr_in[next_comp];
				}
			}
		}
		
		sort(G[c].begin(),G[c].end());
	}
}

inline void get_root () {

	n = Ncomp;
	for ( int i = 1 ; i <= n ; ++i ){
		if ( !gr_in[i] ){
			R = i;
		}
	}
}

void DFS ( int nod , int t ){
	NIV[nod] = NIV[t]+1; up[nod] = t;
	viz[nod] = 1; first[nod] = ++index;
	
	for ( vector<int>::iterator itt = G[nod].begin() ; itt != G[nod].end() ; ++itt ){
		int fiu = (*itt);
		if ( !viz[fiu] ){
			DFS(fiu,nod);
		}
		if ( NIV[up[fiu]] < NIV[up[nod]] ){
			up[nod] = up[fiu];
		}
	}
	
	for ( vector<int>::iterator itt = Gt[nod].begin() ; itt != Gt[nod].end() ; ++itt ){
		int stramos = (*itt);
		if ( NIV[stramos] < NIV[up[nod]] ){
			up[nod] = stramos;
		}
	}
	last[nod] = index;
}

void DFS_tree ( int nod , int t ){

	NIV_arb[nod] = NIV_arb[t] + 1;
	for ( vector<int>::iterator itt = V[nod].begin() ; itt != V[nod].end() ; ++itt ){
		DFS_tree(*itt,nod);
	}
}

inline void build_tree () {

	for ( int i = 1 ; i <= n ; ++i ){
		if ( up[i] ){
			V[up[i]].pb(i);
		}
	}
	
	DFS_tree(R,0);
	
	for ( int i = 1 ; i <= n ; ++i ){
		P[0][i] = up[i];
	}
	for ( int p = 1 ; (1<<p) <= n ; ++p ){
		for ( int i = 1 ; i <= n ; ++i ){
			P[p][i] = P[p-1][ P[p-1][i] ];
		}
	}
}

inline bool stramos ( int x , int y ){
	return first[x] <= first[y] && last[y] <= last[x];
}

inline void solve () {
	
	int q,x,y;
	fscanf(f,"%d",&q);
	for ( int i = 1 ; i <= q ; ++i ){
		fscanf(f,"%d %d",&x,&y);
		x = comp[x]; y = comp[y];
		
		int sol = 0;
		if ( !stramos(x,y) ){
			
			int firstx = x;
			for ( int p = 16 ; p >= 0 ; --p ){
				
				if ( P[p][x] && !stramos(P[p][x],y) ){
					x = P[p][x];
				}
			}
			
			sol = NIV_arb[firstx] - NIV_arb[x] + 1;
		}
		
		fprintf(g,"%d\n",sol);
	}
}

int main () {

	citire();
	
	CTC();
	build_CTC_graph();
	
	get_root();
	DFS(R,0);
	
	build_tree();
	
	solve();
	
	fclose(f);
	fclose(g);
	
	return 0;
}