Cod sursa(job #1219448)

Utilizator danalex97Dan H Alexandru danalex97 Data 14 august 2014 11:02:39
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.42 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;

ifstream F("obiective.in");
ofstream G("obiective.out");

const int N = 100010;
const int debug = 0;

int n,nn,m,mark[N],ord[N],where[N];
int root,ancestor[N],level[N],before[N],after[N],when,dad[N];
set<int> w[N];
vector<int> v[N],vt[N],t[N],stack,tree[N];
int stk[N],str[17][N],dd[N];

void print(int n,vector<int> v[N])
{
    if ( !debug ) return;
    for (int i=1;i<=n;++i)
    {
        cerr<<i<<" : ";
        for (size_t j=0;j<v[i].size();++j)
            cerr<<v[i][j]<<' ';
        cerr<<'\n';
    }
    cerr<<'\n';
}

void dff(int x)
{
    mark[x] = 1;
    for (size_t i=0;i<v[x].size();++i)
    {
        int y = v[x][i];
        if ( mark[y] == 0 )
            dff(y);
    }
    stack.push_back(x);
}

void dfs(int x,int comp)
{
    mark[x] = comp;
    for (size_t i=0;i<vt[x].size();++i)
    {
        int y = vt[x][i];
        if ( mark[y] == 0 )
            dfs(y,comp);
    }
}

void ctc()
{
    for (int i=1;i<=n;++i)
        if ( mark[i] == 0 )
            dff(i);
    memset(mark,0,sizeof(mark));
    for (;!stack.empty();stack.pop_back())
    {
        int x = stack.back();
        if ( mark[x] == 0 )
            dfs(x,++nn);
    }
    for (int x=1;x<=n;++x)
        where[x] = mark[x];
    for (int x=1;x<=n;++x)
        for (size_t j=0;j<v[x].size();++j)
        {
            int y = v[x][j];
            if ( mark[x] != mark[y] )
                w[mark[x]].insert(mark[y]);
        }
}

void dft(int x)
{
    mark[x] = 1;
    for (set<int>::iterator it=w[x].begin();it!=w[x].end();++it)
    {
        int y = *it;
        if ( mark[y] == 0 )
            dft(y);
    }
    stack.push_back(x);
}

bool cmp(int x,int y)
{
    return ord[x] < ord[y];
}

void sortt()
{
    memset(mark,0,sizeof(mark));
    stack.clear();
    for (int i=1;i<=nn;++i)
        if ( mark[i] == 0 )
            dft(i);
    int sz = stack.size();
    root = stack.back();
    for (int i=sz;!stack.empty();stack.pop_back(),--i)
    {
        int x = stack.back();
        ord[x] = sz - i + 1;
    }
    for (int i=1;i<=nn;++i)
    {
        for (set<int>::iterator it=w[i].begin();it!=w[i].end();++it)
        {
            t[i].push_back(*it);
            t[*it].push_back(i);
        }
        sort(t[i].begin(),t[i].end(),cmp);
    }
}

void build(int x)
{
    mark[x] = 1;
    before[x] = ++when;

    if ( x != root ) ancestor[x] = dad[x];
    for (size_t i=0;i<t[x].size();++i)
    {
        int y = t[x][i];
        if ( mark[y] == 0 )
        {
            dad[y] = x;
            level[y] = level[x]+1;
            build(y);

            if ( y != root )
                if ( level[ancestor[y]] < level[ancestor[x]] )
                    ancestor[x] = ancestor[y];
        }
        if ( y != root ) //
            if ( level[y] < level[ancestor[y]] )
                ancestor[x] = y;
    }

    after[x] = ++when;
}

void bancestors(int x)
{
    stk[++stk[0]] = x;
    for (size_t i=0;i<tree[x].size();++i)
    {
        int y = tree[x][i];
        dd[y] = x;
        bancestors(y);
    }
    --stk[0];

    for (int i=0;i<=15;++i)
    {
        if ( stk[0] >= (1<<i) )
            str[x][i] = stk[ stk[0] - (1<<i) + 1 ];
        else
            str[x][i] = root;
    }
}

bool anc(int x,int y)
{
    return before[x] <= before[y] && after[x] >= after[y];
}

int main()
{
    F>>n>>m;
    for (int i=1,x,y;i<=m;++i)
    {
        F>>x>>y;
        v[x].push_back(y);
        vt[y].push_back(x);
    }
    ctc();
    sortt();

    print(nn,t);

    memset(mark,0,sizeof(mark));
    build(root);
    for (int i=1;i<=nn;++i)
        if ( ancestor[i] != 0 )
            tree[ ancestor[i] ].push_back( i );

    print(nn,tree);
    bancestors(root);

    int tt = 0;
    F>>tt;
    for (int i=1,x,y;i<=tt;++i)
    {
        F>>x>>y;
        x = where[x];
        y = where[y];

        if ( anc(x,y) )
            G<<"0\n";
        else
        {
            int now = x, steps = 0;
            for (int j=15;j>=0;--j)
                if ( anc(str[now][j],y) == 0 )
                {
                    now = str[now][j];
                    steps += (1<<j);
                }
            now = dd[now];
            ++steps;
            G<<steps<<'\n';
        }
    }
}