Cod sursa(job #390969)

Utilizator AndreyPAndrei Poenaru AndreyP Data 4 februarie 2010 21:02:46
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.45 kb
#include<stdio.h>
#include<stack>
#include<bitset>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define N 32010
#define M 64010
#define pb push_back
int n,m;
vector<int> a[N],b[N],c[N];
stack<int> st;
bitset<N> inst,bagat;
int ind[N],indlow[N],indice;
int con[N],nc;
int deg[N];
int tata;
int lo[3*N];
int d[18][3*N];
int poz[N],niv[N],lev[N];
int t[16][N];
queue<int> q,q1;
inline void citire()
{
	scanf("%d%d",&n,&m);
	int x,y;
	for(int i=0; i<m; ++i)
	{
		scanf("%d%d",&x,&y);
		a[x].pb(y);
	}
}
inline void vezi(int nod)
{
	for(size_t i=0,lim=a[nod].size(); i<lim; ++i)
	{
		if(bagat[con[a[nod][i]]]==1)
			continue;
                 ++deg[con[a[nod][i]]];
		 b[con[nod]].pb(con[a[nod][i]]);
		 bagat[con[a[nod][i]]]=1;
	}
}
void tarjan(int nod)
{
	ind[nod]=indlow[nod]=++indice;
	inst[nod]=1;
	st.push(nod);
	for(size_t i=0,lim=a[nod].size(); i<lim; ++i)
	{
		if(ind[a[nod][i]]==0)
		{
			tarjan(a[nod][i]);
			if(indlow[a[nod][i]]<indlow[nod])
				indlow[nod]=indlow[a[nod][i]];
		}
		else
		if(inst[a[nod][i]]==1)
		{
			if(indlow[a[nod][i]]<indlow[nod])
				indlow[nod]=indlow[a[nod][i]];
		}
	}
	if(ind[nod]==indlow[nod])
	{
		int nod1;
		++nc;
		bagat.reset();
		bagat[0]=1;
		bagat[nc]=1;
                do
		{
			nod1=st.top();
			inst[nod1]=0;
			con[nod1]=nc;
			st.pop();
                        vezi(nod1);
		}while(nod1!=nod);
	}
}
inline void tareConexe()
{
	for(int i=1; i<=n; ++i)
	{
		if(ind[i]==0)
			tarjan(i);
	}
	indice=0;
	for(int i=1; i<=nc; ++i)
	{
		if(deg[i]==0)
		{
			tata=i;	
			return;
		}
	}
}
void euler(int nod,int h)
{
	poz[nod]=++indice;
	niv[nod]=h;
	d[0][indice]=nod;

        for(size_t i=0,lim=a[nod].size(); i<lim; ++i)
	{
		if(niv[t[0][nod]]>niv[a[nod][i]])
			t[0][nod]=a[nod][i];
	}
	for(size_t i=0,lim=c[nod].size(); i<lim; ++i)
	{
	        t[0][c[nod][i]]=nod;
		euler(c[nod][i],h+1);
	        if(niv[t[0][c[nod][i]]]<niv[t[0][nod]])
	        	t[0][nod]=t[0][c[nod][i]];
		++indice;
		d[0][indice]=nod;
	}
}
inline int minim1(int x,int y)
{
	if(niv[x]<niv[y])
		return x;
	return y;
}
inline int minim(int x,int y)
{
	if(x<y)
		return x;
	return y;
}
inline void rmq()
{
	lo[2]=1;
	int dim,dim1;
	for(int i=3; i<=indice; ++i)
		lo[i]=lo[i>>1]+1;
        for(int i=1; i<=lo[indice]; ++i)
	{
		dim=1<<i;
		dim1=dim>>1;
		for(int j=1; j+dim-1<=indice; ++j)
			d[i][j]=minim1(d[i-1][j],d[i-1][j+dim1]);
	}
}
inline int lca(int x,int y)
{
	if(poz[x]>poz[y])
		swap(x,y);
	int cat=lo[poz[y]-poz[x]+1];
	return minim1(d[cat][poz[x]],d[cat][poz[y]-(1<<cat)+1]);
}
/*inline bool spune(int nod,int care,int cat)
{
	for(int i=0; (1<<i)<=care; ++i)
	{
		if((care&(1<<i))!=0)
			nod=t[i][nod];
	}
	if(niv[nod]<=niv[cat])
		return true;
	return false;
}  */
inline void rezolva()
{
	int x,y;
	scanf("%d%d",&x,&y);
	if(con[x]==con[y])
	{
		fputs("0\n",stdout);
		return;
	}
	x=con[x];
	y=con[y];
	int cat=lca(x,y);
	if(x==cat)
	{
		fputs("0\n",stdout);
		return;
	}
       /* int p=1,u=lev[x];
	while(p<u)
	{
		int m1=(p+u)>>1;
		if(spune(x,m1,cat))
			u=m1;
		else
			p=m1+1;
	}
	while(p!=1 && spune(x,p-1,cat))
		--p;
	while(spune(x,p,cat)==false)
		++p;
	printf("%d\n",p); */
        int rez=0;
	int i=lo[lev[x]];
	while(i>=0)
	{
		if(niv[t[i][x]]<=niv[cat])
		{
			--i;
			continue;
		}
                rez+=(1<<i);
		x=t[i][x];
		if(x==0)
			exit(4);
	}
	if(niv[x]>niv[cat])
		++rez;   
	printf("%d\n",rez);  
}
void sterge(vector<int> &x)
{
	vector<int> y;
	y.swap(x);
}
inline void sortareTopologica()
{
	ind[0]=1;
	ind[1]=tata;
	int next;
	for(int i=1; i<=ind[0]; ++i)
	{
		for(size_t j=0,lim=b[ind[i]].size(); j<lim; ++j)
		{
			next=b[ind[i]][j];
                        --deg[next];
			a[next].pb(ind[i]);
			if(deg[next]==0)
			{
				ind[++ind[0]]=next;
                                c[ind[i]].pb(next);
			}
		}
	}
}
inline void stramosi()
{
	bool ok=true;
	int dim,dim1;
	for(int i=1; ok; ++i)
	{
		ok=false;
		dim=1<<i;
		dim1=dim>>1;
		for(int j=1; j<=nc; ++j)
		{
			if(dim>lev[j])
				continue;
			ok=true;
			t[i][j]=t[i-1][t[i-1][j]];
		}
	}
}
void dfs(int nod)
{
	if(inst[nod]==1)
		return;
	inst[nod]=1;
	dfs(t[0][nod]);
	lev[nod]=lev[t[0][nod]]+1;
}
int main()
{
	freopen("obiective.in","r",stdin);
	freopen("obiective.out","w",stdout);
	citire();
        tareConexe();
	for(int i=1; i<=n; ++i)
		sterge(a[i]);
	sortareTopologica();
        euler(tata,0);
	inst.reset();
	lev[tata]=0;
	inst[tata]=1;
	for(int i=1; i<=nc; ++i)
	{
		if(inst[i]==0)
			dfs(i);
	}
        rmq();
	stramosi();
        int T;
	scanf("%d",&T);
	for(int i=0; i<T; ++i)
		rezolva();
	return 0;
}