Cod sursa(job #1615551)

Utilizator alex_HarryBabalau Alexandru alex_Harry Data 26 februarie 2016 17:47:53
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.58 kb
#include <fstream>
#include <vector>
#include <cstring>
using namespace std;
ifstream f("obiective.in");
ofstream g("obiective.out");
const int NMax = 32005;
int N,M,O[NMax],K,NRC;
vector <int> G[NMax],GT[NMax],CTC[NMax],GG[NMax];
int Level[NMax],MinLev[NMax],Father[20][NMax],Poz[NMax],Father2[20][NMax],F[NMax],F2[NMax];
int Res[100005];
struct Query
{
    int x,y,poz;
};
bool Use[NMax];
void Read()
{
    f>>N>>M;
    for(int i=1;i<=M;i++)
        {
            int x,y;
            f>>x>>y;
            G[x].push_back(y);
            GT[y].push_back(x);
        }
}
void DFP(int Nod)
{
    Use[Nod]=1;
    for(unsigned int i=0;i<G[Nod].size();i++)
        {
            int Vecin=G[Nod][i];
            if(!Use[Vecin])
                DFP(Vecin);
        }
    O[++K]=Nod;
}

void DFM(int Nod)
{
    Use[Nod]=1;CTC[NRC].push_back(Nod);
    Poz[Nod]=NRC;
    for(unsigned int i=0;i<GT[Nod].size();i++)
        {
            int Vecin=GT[Nod][i];
            if(!Use[Vecin])
                DFM(Vecin);
        }
}

void Kosaraju()
{
    for(int i=1;i<=N;i++)
        {
            if(!Use[i])
                DFP(i);
        }
    memset(Use,0,sizeof(Use));
    for(int i=K;i>=1;i--)
        {
            if(!Use[O[i]])
            {
                NRC++;
                DFM(O[i]);
            }

        }
}

void buildCTCGraph()
{
    for(int i=1;i<=N;i++)
        GT[i].clear();
    for(int i=1;i<=NRC;i++)
    {
        memset(Use,0,sizeof(Use));
        Use[i]=1;
        for(int j=0;j<CTC[i].size();j++)
        {
            int node=CTC[i][j];
            for(int k=0;k<G[node].size();k++)
                if(Use[Poz[G[node][k]]]==0)
                {
                    Use[Poz[G[node][k]]]=1;
                    GG[i].push_back(Poz[G[node][k]]);
                    GT[Poz[G[node][k]]].push_back(i);
                }
        }
    }
    for(int i=1;i<=NRC;i++)
    {
        G[i].clear();
        G[i]=GG[i];
    }
}

void DFS(int node)
{
    Use[node]=1;
    for(int i=0;i<G[node].size();i++)
    {
        int neighb=G[node][i];
        if(Use[neighb]==0)
        {
            F[neighb]=node;
            Level[neighb]=Level[node]+1;
            DFS(neighb);
        }
    }
}

void DFS2(int node)
{
    Use[node]=1;
    MinLev[node]=max(0,Level[node]-1);
    F2[node]=F[node];
    for(int i=0;i<G[node].size();i++)
    {
        int neighb=G[node][i];
        if(Use[neighb]==0)
        {
            DFS2(neighb);
            if(MinLev[node]>MinLev[neighb])
            {
                MinLev[node]=MinLev[neighb];
                F2[node]=F2[neighb];
            }
        }
    }
    for(int i=0;i<GT[node].size();i++)
    {
        int neighb=GT[node][i];
        if(Level[neighb]<MinLev[node])
        {
            MinLev[node]=Level[neighb];
            F2[node]=neighb;
        }
    }
}
int lca(int x,int y)
{
    if(Level[x]<Level[y])
        swap(x,y);
    int log1,log2;
    for(log1=1;(1<<log1)<Level[x];++log1);
    for(log2=1;(1<<log2)<Level[y];++log2);
    for(int k = log1; k >= 0; --k)
        if(Level[x] - (1 << k) >= Level[y])
            x = Father[k][x];
    if(x == y) return x;
    for(int k = log2; k >= 0; --k)
        if(Father[k][x] && Father[k][x] != Father[k][y])
            x = Father[k][x],
            y = Father[k][y];
    return Father[0][x];
}
void precalcFather()
{
    for(int i=1;i<=NRC;i++)
        Father[0][i]=F2[i],Father2[0][i]=F[i];
    for(int j=1;(1<<j)<=NRC;j++)
        for(int i=1;i<=NRC;i++)
            Father[j][i]=Father[j-1][Father[j-1][i]],Father2[j][i]=Father2[j-1][Father2[j-1][i]];
}

int query(int x,int y)
{
    int ans=0;
    if(x==y)
        return 0;
    for(int i=15;i>=0;i--)
        if(Father[i][x]!=0 && Level[Father[i][x]]>Level[y])
        {
            ans+=(1<<i);
            x=Father[i][x];
        }
    return ans+1;
}
int findSource()
{
    for(int i=1;i<=NRC;i++)
        if(GT[i].size()==0)
            return i;
}

void Solve()
{
    int T;
    f>>T;
    for(int i=1;i<=T;i++)
    {
        int x,y;
        f>>x>>y;
        x=Poz[x];y=Poz[y];
        if(x==y)
        {
            g<<0<<"\n";
            continue;
        }
        int p=lca(x,y);
        g<<query(x,p)<<"\n";
    }
}
int main()
{
    Read();
    Kosaraju();
    buildCTCGraph();
    memset(Use,0,sizeof(Use));
    int S=findSource();
    Level[S]=1;
    DFS(S);
    memset(Use,0,sizeof(Use));
    DFS2(S);
    memset(Use,0,sizeof(Use));
    precalcFather();
    Solve();
    return 0;
}