Cod sursa(job #74044)

Utilizator astronomyAirinei Adrian astronomy Data 23 iulie 2007 16:42:15
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.35 kb
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;

#define INF 999999
#define MAX_N 32100
#define LOG_N 16
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define pb push_back

int N, M, Q, K, L, Min[LOG_N][MAX_N], Nod[LOG_N][MAX_N], T[LOG_N][MAX_N];
int root, niv[MAX_N], cc[MAX_N], list[MAX_N];
int V[MAX_N], deg[MAX_N], tata[MAX_N];
char viz[MAX_N];

vector<int> G[MAX_N], Gc[MAX_N], Gt[MAX_N], Ga[MAX_N];

void df_1(int x)
{
    vector<int>::iterator it;

    for(it = G[x].begin(); it != G[x].end(); ++it)
     if(!viz[*it])
        viz[*it] = 1, df_1(*it);

    list[++list[0]] = x;
}

void df_2(int x)
{
    vector<int>::iterator it;

    for(it = Gt[x].begin(); it != Gt[x].end(); ++it)
     if(!viz[*it])
        cc[*it] = K, viz[*it] = 1, df_2(*it);
}

void df_3(int x)
{
    vector<int>::iterator it;

    for(it = Ga[x].begin(); it != Ga[x].end(); ++it)
    {
        df_3(*it);
        if(Min[L][x] > Min[L][*it])
            Min[L][x] = Min[L][*it], Nod[L][x] = Nod[L][*it];
    }
}

void df_4(int x)
{
    vector<int>::iterator it;

    for(it = Ga[x].begin(); it != Ga[x].end(); ++it)
        niv[*it] = niv[x]+1, tata[*it] = x, df_4(*it);
}

void baga_conexe(void)
{
    int i, j, x;
    vector<int>::iterator it;

    for(i = 1; i <= N; i++)
     if(!viz[i])
        viz[i] = 1, df_1(i);

    memset(viz, 0, sizeof(viz));

    for(i = N; i >= 1; i--)
     if(!viz[ list[i] ])
        viz[ list[i] ] = 1, cc[ list[i] ] = ++K, df_2(list[i]);

    for(x = 1; x <= N; x++)
     for(it = G[x].begin(); it != G[x].end(); ++it)
      if(cc[x] != cc[*it])
        Gc[ cc[x] ].pb( cc[*it] ), deg[ cc[*it] ]++;
}

void baga_arbore_lca(void)
{
    int i, j, k, x;
    vector<int>::iterator it;

    for(x = 1; x <= K; x++)
     if(deg[x] == 0)
        root = V[++V[0]] = x;

    for(i = 1; i <= K; i++)
    {
        x = V[i];
        for(it = Gc[x].begin(); it != Gc[x].end(); ++it)
        {
            deg[*it]--;
            if(deg[*it] == 0)
                Ga[x].pb(*it), V[++V[0]] = *it;
        }
    }

    df_4(root);

    for(i = 1; i <= K; i++)
        T[0][i] = tata[i];
    for(i = 1; i < LOG_N; i++)
     for(j = 1; j <= K; j++)
        T[i][j] = T[i-1][ T[i-1][j] ];
}

void preproc_minim(void)
{
    int i, j, x, k;
    vector<int>::iterator it;
    
    for(i = 1; i <= K; i++)
     if(i != root)
        Min[0][i] = INF;

    for(i = 0; i < LOG_N; i++)
        Nod[i][root] = root;

    for(x = 1; x <= K; x++)
    {
        for(it = Gc[x].begin(); it != Gc[x].end(); ++it)
         if(niv[x] < Min[0][*it])
            Min[0][*it] = niv[x], Nod[0][*it] = x;
    }

    L = 0, df_3(root);
    
    for(i = 1; i < LOG_N; i++)
    {
        for(x = 1; x <= K; x++)
            Min[i][x] = Min[i-1][ Nod[i-1][x] ],
            Nod[i][x] = Nod[i-1][ Nod[i-1][x] ];
        L = i, df_3(root);
    }
}

int lca(int x, int y)
{
    int t, p;

    if(niv[x] < niv[y])
    {
        for(p = 15; p >= 0; p--)
         if(niv[y]-(1<<p) >= niv[x])
            y = T[p][y];
    }
    else
    {
        for(p = 15; p >= 0; p--)
         if(niv[x]-(1<<p) >= niv[y])
            x = T[p][x];
    }

    if(x == y)
        return x;

    for(p = 15; p >= 0; p--)
     if(niv[x]-(1<<p) >= 0 && T[p][x] != T[p][y])
        x = T[p][x], y = T[p][y];

    return tata[x];
}

int rezolva(int x, int y) // de la x la y
{
    int t, p, q, ret = 0;

    if(cc[x] == cc[y])
        return 0;

    x = cc[x], y = cc[y];
    t = lca(x, y), p = niv[t];

    if(x == t)
        return 0;
        
    for(q = 15; q >= 0; q--)
     if(niv[x]-(1<<q) >= 0 && Min[q][x] > p)
        x = Nod[q][x], ret += (1<<q);

    return ret+1;
}

void read_and_solve(void)
{
    int i, a, b;

    scanf("%d %d\n", &N, &M);

    for(i = 1; i <= M; i++)
    {
        scanf("%d %d\n", &a, &b);
        G[a].pb(b), Gt[b].pb(a);
    }

    baga_conexe();
    baga_arbore_lca();
    preproc_minim();

    scanf("%d\n", &Q);

    for(i = 1; i <= Q; i++)
    {
        scanf("%d %d\n", &a, &b);
        printf("%d\n", rezolva(a, b));
    }
}

int main(void)
{
    freopen("obiective.in", "rt", stdin);
    freopen("obiective.out", "wt", stdout);

    read_and_solve();

    return 0;
}