Cod sursa(job #65543)

Utilizator filipbFilip Cristian Buruiana filipb Data 10 iunie 2007 18:07:17
Problema Obiective Scor Ascuns
Compilator cpp Status done
Runda Marime 4.81 kb
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>

using namespace std;

#define minim(a, b) ((a < b) ? a : b)
#define CLEAR(x) memset(x, 0, sizeof(x))
#define pb push_back
#define INF 900000000
#define NMax 32005
#define LG 16

int N, t[NMax], dep[NMax], uz[NMax], log[NMax], timp, conex, rad;
int A[LG][NMax], up[LG][NMax], c[NMax], low[NMax], U[NMax], deg[NMax];
int t_in[NMax], t_out[NMax];
vector<int> G[NMax], GT[NMax];

void bucla_infinita(void)
{ for (;;); }

int cmp(const int& a, const int& b)
{ return t[a] > t[b]; }

void df_times(int nod, int graf)
{
	vector<int>::iterator it;

    uz[nod] = 1;

    if (!graf) // parcurgere in G
    {
	    for (it = G[nod].begin(); it != G[nod].end(); it++)
    		if (!uz[*it])
        	    df_times(*it, graf);
		t[++timp] = nod;
    }
    else // parcurgere in GT
    {
	    for (it = GT[nod].begin(); it != GT[nod].end(); it++)
    		if (!uz[*it])
        	    df_times(*it, graf);
		t[nod] = (++timp);
    }

}

void df_gt(int nod)
{
	vector<int>::iterator it;

    c[nod] = conex;
    for (it = GT[nod].begin(); it != GT[nod].end(); it++)
    	if (!c[*it])
            df_gt(*it);
}

void df_levels(int nod)
{
	vector<int>::iterator it;

    for (it = GT[nod].begin(); it != GT[nod].end(); it++)
    	if (!dep[*it])
        {
        	U[*it] = nod;
        	dep[*it] = dep[nod] + 1;
            df_levels(*it);
		}
        
}

void df(int nod)
{
	int h;
	vector<int>::iterator it;

	up[0][nod] = U[nod];
    for (h = 1; h <= log[dep[nod]-1]; h++)
   		up[h][nod] = up[h-1][up[h-1][nod]];        

    uz[nod] = 1;
    for (it = GT[nod].begin(); it != GT[nod].end(); it++)
    	if (U[*it] == nod)
        {            
        	if (dep[low[*it]] > dep[nod])
            	low[*it] = nod;
                
            df(*it);

            if (dep[low[nod]] > dep[low[*it]])
            	low[nod] = low[*it];
        }
}

void df_up(int nod, int lev)
{
    int h;
    vector<int>::iterator it;

    deg[nod] = lev; A[0][nod] = low[nod];
    t_in[nod] = (++timp);
    for (h = 1; h <= log[lev-1]; h++)
        A[h][nod] = A[h-1][A[h-1][nod]];

    for (it = G[nod].begin(); it != G[nod].end(); it++)
    	df_up(*it, lev+1);

	t_out[nod] = (++timp);
}

int LCA(int x, int y)
{
	int h;
    
	for (; dep[x] > dep[y]; x = up[log[dep[x]-dep[y]]][x]);
    for (; dep[y] > dep[x]; y = up[log[dep[y]-dep[x]]][y]);

    if (x == y) return x;

    for (h = log[dep[x]-1]; h >= 0; h--)
    	if (up[h][x] != up[h][y])
			x = up[h][x], y = up[h][y];
            
	return up[0][x];
}

int stramos(int x, int y)
{ return t_in[x] <= t_in[y] && t_out[y] <= t_out[x]; }

int main(void)
{
	int M, T, L, i, u, v, bst;
    vector<int>::iterator it;
    
	freopen("obiective.in", "r", stdin);
    freopen("obiective.out", "w", stdout);

    for (i = 2; i < NMax-1; i++)
		log[i] = log[i/2] + 1;

    scanf("%d %d", &N, &M);
    for (; M; M--)
    {
    	scanf("%d %d", &u, &v);
        G[u].pb(v); GT[v].pb(u);
    }

    for (i = 1; i <= N; i++)
    	if (!uz[i])
		    df_times(i, 0);

    for (i = N, timp = 0; i >= 1; i--)
    	if (!c[t[i]])
        { ++conex; df_gt(t[i]); }

	for (i = 1; i <= N; i++)
    	GT[i].clear();

	for (i = 1; i <= N; i++)
    	for (it = G[i].begin(); it != G[i].end(); it++)
        	if (c[i] != c[*it])
            {
	            GT[c[i]].pb(c[*it]);
                deg[c[*it]]++;
            }
            
	CLEAR(uz); CLEAR(t);

    for (i = 1, timp = 0; i <= N; i++)
    	if (!uz[i])
		    df_times(i, 1);

    for (i = 1; i <= conex; i++)
    	sort(GT[i].begin(), GT[i].end(), cmp);

	for (i = 1; i <= conex; i++)
    	if (!deg[i])
        {
        	if (rad)
            	bucla_infinita();
                
        	rad = i;
        }

    dep[rad] = 1; df_levels(rad);
    dep[conex+1] = INF;

    for (i = 1; i <= conex; i++)
    	low[i] = conex+1;

	for (i = 1; i <= conex; i++)
    	for (it = GT[i].begin(); it != GT[i].end(); it++)
            if (U[*it] != i && dep[low[*it]] > dep[i]) // muchie inainte
            	low[*it] = i;

    CLEAR(uz); CLEAR(deg);
    low[rad] = 1; df(rad);

    for (i = 1; i <= N; i++) G[i].clear();
    for (i = 2; i <= N; i++)
    	G[low[i]].pb(i);

	timp = 0; df_up(rad, 1);

    for (scanf("%d", &T); T; T--)
    {
    	scanf("%d %d", &u, &v);
        u = c[u]; v = c[v];
        
        L = LCA(u, v);

        if (u == L)
        	printf("0\n");
		else
        {
        	bst = deg[u];
            for (i = log[deg[u]-1]; i >= 0; i--)
            	if (A[i][u] && !stramos(A[i][u], L))
                    u = A[i][u];
            u = A[0][u];

            bst -= deg[u];

			printf("%d\n", bst);
        }
            
    }
                
	return 0;
}