Cod sursa(job #593099)

Utilizator GavrilaVladGavrila Vlad GavrilaVlad Data 1 iunie 2011 12:06:24
Problema Obiective Scor 70
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.76 kb
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>

using namespace std;

#define maxn 100010
#define mlog 18

int n, q, m, nc, x, a, b;
int f[maxn], s[maxn], p[maxn], g[maxn], ctc[maxn], niv[maxn];
vector<int> vi[maxn], invi[maxn];
vector<int> v[maxn], inv[maxn];
map<pair<int, int>, int> mp;
int st[mlog][maxn], d[mlog][maxn];

void df1(int nod)
{
    if(f[nod])
        return;
    f[nod]=1;

    for(int i=0; i<vi[nod].size(); ++i)
        df1(vi[nod][i]);

    s[++s[0]]=nod;
}

void df2(int comp, int nod)
{
    if(f[nod])
        return;
    f[nod]=1;

    ctc[nod]=comp;
    for(int i=0; i<invi[nod].size(); ++i)
        df2(comp, invi[nod][i]);
}

void tare_conexe()
{
    int fiu;
    for(int i=1; i<=n; ++i)
        if(!f[i])
            df1(i);

    memset(f, 0, sizeof(f));
    for(int i=n; i; --i)
        if(!f[s[i]])
            df2(++nc, s[i]);

    for(int i=1; i<=n; ++i)
        for(int j=0; j<vi[i].size(); ++j)
        {
            fiu=vi[i][j];
            if(ctc[i]==ctc[fiu])
                continue;
            if(mp[make_pair(ctc[i], ctc[fiu])]==0)
            {
                ++g[ctc[i]];
                mp[make_pair(ctc[i], ctc[fiu])]=1;
                v[ctc[i]].push_back(ctc[fiu]);
                inv[ctc[fiu]].push_back(ctc[i]);
            }
        }
}

inline int cmp(int a, int b)
{
    return p[a]>p[b];
}

void s_topologica()
{
    int nod, fiu;

    s[0]=0;
    for(int i=1; i<=nc; ++i)
        if(g[i]==0)
            s[++s[0]]=i;

    for(int i=1; i<=nc; ++i)
    {
        nod=s[i];
        p[nod]=i;

        for(int j=0; j<inv[nod].size(); ++j)
        {
            fiu=inv[nod][j];
            --g[fiu];
            if(!g[fiu])
                s[++s[0]]=fiu;
        }
    }

    for(int i=1; i<=nc; ++i)
        sort(v[i].begin(), v[i].end(), cmp);
}

void df(int nod, int tata)
{
    int fiu;
    f[nod]=1;

    st[0][nod]=tata;
    niv[nod]=niv[tata]+1;
    d[0][nod]=nc+1;

    for(int i=0; i<v[nod].size(); ++i)
    {
        fiu=v[nod][i];
        if(f[fiu])
            continue;
        df(fiu, nod);
        if(niv[d[0][nod]]>niv[d[0][fiu]])
            d[0][nod]=d[0][fiu];
    }

    for(int i=0; i<inv[nod].size(); ++i)
    {
        fiu=inv[nod][i];
        if(niv[d[0][nod]]>niv[fiu])
            d[0][nod]=fiu;
    }
}

int lca(int a, int b)
{
    for(int i=mlog-1; i>=0; --i)
    {
        if(st[i][a]==0)
            continue;
        if(niv[st[i][a]]>=niv[b])
            a=st[i][a];
    }

    for(int i=mlog-1; i>=0; --i)
    {
        if(st[i][b]==0)
            continue;
        if(niv[st[i][b]]>=niv[a])
            b=st[i][b];
    }

    if(a==b)
        return a;

    for(int i=mlog-1; i>=0; --i)
    {
        if(st[i][a]==0)
            continue;
        if(st[i][a]!=st[i][b])
        {
            a=st[i][a];
            b=st[i][b];
        }
    }
    return st[0][a];
}

int solve(int a, int x)
{
    if(a==x)
        return 0;
    int sol=0;
    for(int i=mlog-1; i>=0; --i)
    {
        if(niv[d[i][a]]>niv[x])
        {
            a=d[i][a];
            sol+=(1<<i);
        }
    }
    return sol+1;
}

int main()
{
    freopen("obiective.in", "r", stdin);
    freopen("obiective.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for(int i=1; i<=m; ++i)
    {
        scanf("%d%d", &a, &b);
        vi[a].push_back(b);
        invi[b].push_back(a);
    }

    tare_conexe();
    s_topologica();

    memset(f, 0, sizeof(f));
    niv[nc+1]=nc+1;
    df(s[nc], 0);

    for(int i=1; i<mlog; ++i)
        for(int j=1; j<=nc; ++j)
        {
            st[i][j]=st[i-1][st[i-1][j]];
            d[i][j]=d[i-1][d[i-1][j]];
        }

    scanf("%d", &q);

    while(q--)
    {
        scanf("%d%d", &a, &b);
        a=ctc[a];
        b=ctc[b];
        x=lca(a, b);
        printf("%d\n", solve(a, x));
    }
    return 0;
}