Cod sursa(job #388980)

Utilizator AndreyPAndrei Poenaru AndreyP Data 31 ianuarie 2010 16:10:18
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.7 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*M];
int d[19][3*M];
int poz[M],niv[M];
int t[N];
queue<int> q;
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;
		 //printf("%d --> %d\n",con[nod],con[a[nod][i]]);
	}
}
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]=niv[nod];
	for(size_t i=0,lim=c[nod].size(); i<lim; ++i)
	{
		euler(c[nod][i],h+1);
		++indice;
		d[0][indice]=niv[nod];
	}
}
inline int minim(int x,int y)
{
	if(x<y)
		return x;
	return y;
}
inline void rmq()
{
	lo[2]=1;
	int dim,dim1;
	if(indice>=3*M)
		exit(4);
	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]=minim(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 minim(d[cat][poz[x]],d[cat][poz[y]-(1<<cat)+1]);
}
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];
	if(inst[y]==1)
		y+=nc;
	int cat=lca(x,y);
        printf("%d\n",niv[x]-cat);
}
void sterge(vector<int> &x)
{
	vector<int> y;
	y.swap(x);
}
inline void bfs()
{
	inst.reset();
	q.push(tata);
	inst[tata]=1;
	int now,next;
	while(!q.empty())
	{
		now=q.front();
		q.pop();
                for(size_t i=0,lim=b[now].size(); i<lim; ++i)
		{
			next=b[now][i];
			if(inst[next]==1)
				continue;
			t[next]=now;
			inst[next]=1;
			q.push(next);
			c[now].pb(next);
		}
	}
}
inline void sortareTopologica()
{
	inst.reset();
	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];
			if(deg[next]==0)
			{
				ind[++ind[0]]=next;
				if(inst[ind[i]]==1)
				{
					c[ind[i]+nc].pb(next+nc);
					inst[next]=1;
				}
				else
				if(t[next]!=ind[i])
				{
					c[ind[i]].pb(next+nc);
					inst[next]=1;
				}
			}
		}
	}
}
int main()
{
	freopen("obiective.in","r",stdin);
	freopen("obiective.out","w",stdout);
	citire();
        tareConexe();
	//if(indice!=0)
	//	exit(4);
	//if(nrm!=nc-1)
	//	exit(4);
	for(int i=1; i<=n; ++i)
		sterge(a[i]);
	bfs();
	sortareTopologica();
	for(int i=1; i<=nc; ++i)
		sterge(b[i]);
        euler(tata,0);
        rmq();
        int T;
	scanf("%d",&T);
	for(int i=0; i<T; ++i)
		rezolva();
	return 0;
}