Cod sursa(job #1044833)

Utilizator tzipleatudTudor Tiplea tzipleatud Data 30 noiembrie 2013 15:15:26
Problema Obiective Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 4.64 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <stack>
#define NM 32010
#define LOGM 16

using namespace std;

ifstream f("obiective.in");
ofstream g("obiective.out");

int N, C, M, T, K;
int Level[NM], MinLevel[NM];
int WComponent[NM];
bool InStack[NM], NotRoot[NM];
vector<int> GI[NM], G[NM], GInverse[NM];
stack<int> S;
int Ancestors[LOGM][NM], UpMost[LOGM][NM];
int Depth[NM], MinDepth[NM];

void Read ()
{
    f >> N >> M;
    for (int i=1; i<=M; i++)
    {
        int a, b;
        f >> a >> b;
        GI[a].push_back(b);
    }
}

void DoTarjan (int node)
{
    MinLevel[node]=Level[node]=++K;
    S.push(node);
    InStack[node]=1;

    for (vector<int>::iterator it=GI[node].begin(); it!=GI[node].end(); ++it)
        if (!Level[*it])
        {
            DoTarjan(*it);
            MinLevel[node]=min(MinLevel[node], MinLevel[*it]);
        }
        else
        {
            if (InStack[*it])
                MinLevel[node]=min(MinLevel[node], MinLevel[*it]);
        }

    if (MinLevel[node]==Level[node])
    {
        ++C;

        for (; !S.empty(); )
        {
            int cnode=S.top();
            WComponent[cnode]=C;
            S.pop();
            InStack[cnode]=0;
            if (cnode==node)
                break;
        }
    }
}

void CTC ()
{
    for (int i=1; i<=N; i++)
        if (!Level[i])
            DoTarjan(i);

    for (int i=1; i<=N; i++)
        for (vector<int>::iterator it=GI[i].begin(); it!=GI[i].end(); ++it)
            if (WComponent[i]!=WComponent[*it])
            {
                G[WComponent[i]].push_back(WComponent[*it]);
                NotRoot[WComponent[*it]]=1;
            }

    for (int i=1; i<=C; i++)
    {
        sort(G[i].begin(), G[i].end());
        G[i].resize(unique(G[i].begin(), G[i].end())-G[i].begin());
        for (vector<int>::iterator it=G[i].begin(); it!=G[i].end(); ++it)
            GInverse[*it].push_back(i);
    }
}

void DFInverse (int node)
{
    int pos=0;
    MinDepth[node]=NM;
    for (vector<int>::iterator it=GInverse[node].begin(); it!=GInverse[node].end(); ++it)
    {
        if (!Depth[*it])
            DFInverse(*it);
        if (Depth[*it]>Depth[node])
        {
            Depth[node]=Depth[*it];
            pos=*it;
        }
        MinDepth[node]=min(MinDepth[node], MinDepth[*it]);
    }

    if (MinDepth[node]==NM)
        MinDepth[node]=0;
    MinDepth[node]++;
    Depth[node]++;
    Ancestors[0][node]=pos;
}

void DF (int node)
{
    for (vector<int>::iterator it=G[node].begin(); it!=G[node].end(); ++it)
    {
        if (!UpMost[0][*it])
            DF(*it);
        if (Depth[UpMost[0][*it]]<Depth[UpMost[0][node]])
            UpMost[0][node]=UpMost[0][*it];
    }

    for (vector<int>::iterator it=GInverse[node].begin(); it!=GInverse[node].end(); ++it)
        if (Depth[*it]<Depth[UpMost[0][node]])
            UpMost[0][node]=*it;
}

void BuildAncestors ()
{
    for (int i=1; i<=C; i++)
        if (!Depth[i])
            DFInverse(i);

    Depth[0]=NM;
    for (int i=1; i<=C; i++)
        if (!UpMost[0][i])
            DF(i);

    for (int j=1; (1 << j)<=C; j++)
        for (int i=1; i<=C; i++)
        {
            Ancestors[j][i]=Ancestors[j-1][Ancestors[j-1][i]];
            UpMost[j][i]=UpMost[j-1][UpMost[j-1][i]];
        }
}

int LCA (int a, int b)
{
    if (Depth[a]>Depth[b])
        swap(a, b);

    int log1, log2, k;
    for (log1=0; (1 << log1)<Depth[a]; ++log1);
    for (log2=0; (1 << log2)<Depth[b]; ++log2);

    for (k=log2; k>=0; k--)
        if (Depth[b]-(1 << k)>=Depth[a])
            b=Ancestors[k][b];

    if (a==b) return a;

    for (k=log1; k>=0; k--)
        if (Ancestors[k][a]!=0 && Ancestors[k][a]!=Ancestors[k][b])
        {
            a=Ancestors[k][a];
            b=Ancestors[k][b];
        }

    return Ancestors[0][a];
}

int GetDist (int a, int t)
{
    if (Depth[a]<=Depth[t])
        return 0;

    int ret=0, k, log;
    for (log=0; (1 << log)<Depth[a]; ++log);

    for (k=log; k>=0; k--)
        if (UpMost[k][a] && Depth[UpMost[k][a]]>Depth[t])
        {
            a=UpMost[k][a];
            ret+=1 << k;
        }
    if (Depth[a]>Depth[t])
        ret++;

    return ret;
}

void Solve ()
{
    Depth[0]=0;
    for (f >> T; T>=1; T--)
    {
        int a, b, c;
        f >> a >> b;
        a=WComponent[a];
        b=WComponent[b];
        c=LCA(a, b);
        g << GetDist(a, c) << '\n';
    }
}

int main ()
{
    Read();
    CTC();
    BuildAncestors();
    Solve();

    f.close();
    g.close();

    return 0;
}