Cod sursa(job #1266736)

Utilizator japjappedulapPotra Vlad japjappedulap Data 19 noiembrie 2014 00:45:35
Problema Obiective Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.81 kb
#include <algorithm>
#include <fstream>
#include <stack>
#include <vector>
using namespace std;

#define N_SIZE 32001

ifstream is ("obiective.in");
ofstream os ("obiective.out");

int index[N_SIZE], L[N_SIZE], idx, comps, Gr[N_SIZE];
bool B[N_SIZE], b[N_SIZE];
stack <int> S;
vector <int> Gx[N_SIZE], C;

int Ap[N_SIZE], euler, RMQ[18][N_SIZE*2];

int N, M, T, root, Q;
vector <int> G[N_SIZE];

bool rev;
int x, y, lev, k, niva, nivb;

void TJ(int x);
void DFS(int x, int l);
void CreateTree();
void RangeMinimumQuery();
int QUERY(int a, int b);

int main()
{
    is >> N >> M;
    for (int i = 1, a, b; i <= M; ++i)
    {
        is >> a >> b;
        Gx[a].push_back(b);
    }
    CreateTree();
    DFS(root, 1);
    RangeMinimumQuery();
    is >> Q;
    for (int i = 1, a, b; i <= Q; ++i)
    {
        is >> a >> b;
        os << QUERY(Gr[a], Gr[b]) << '\n';
    }
    is.close();
    os.close();
};

int QUERY(int a, int b)
{
    rev = 0;
    niva = RMQ[0][Ap[a]];
    nivb = RMQ[0][Ap[b]];
    x = Ap[a];
    y = Ap[b];
    if (x > y) swap(x, y), rev = 1;
    k = 0;
    for (int Z = 1; Z <= (y-x); Z*=2, ++k); --k;
    lev = min(RMQ[k][y-(1<<k)+1], RMQ[k][x]);
    return niva-lev;
};

void RangeMinimumQuery()
{
    RMQ[0][euler] = 1;
    for (int i = 1; (1<<i) <= euler; ++i)
        for (int j = 1; j+(1<<i)-1 <= euler; ++j)
            RMQ[i][j] = min(RMQ[i-1][j], RMQ[i-1][j+(1<<i-1)]);
};

void DFS(int x, int l)
{
    b[x] = 1;
    RMQ[0][++euler] = l;
    Ap[x] = euler;
    for (const auto& y : G[x])
    {
        DFS(y, l+1);
        RMQ[0][++euler] = l;
    }
};


void CreateTree()
{
    for (int i = 1; i <= N; ++i)
        if (index[i] == 0)
            TJ(i);
    for (int i = 1; i <= comps; ++i)
    {
        sort (G[i].begin(), G[i].end());
        G[i].erase (unique(G[i].begin(), G[i].end()), G[i].end());
        for (const auto& f : G[i])
            b[f] = 1;
    }
    for (int i = 1; i <= comps; ++i)
        if (b[i] == 0)  { root = i; break; }
    for (int i = 1; i <= comps; ++i)
        b[i] = 0;
};


void TJ(int x)
{
    B[x] = 1; S.push(x);
    index[x] = L[x] = ++idx;
    for (const auto& y : Gx[x])
        if (index[y] == 0)
        {
            TJ(y);
            L[x] = min(L[x], L[y]);
        }
        else if (B[y] == 1)
            L[x] = min(L[x], L[y]);
    if (index[x] == L[x])
    {
        ++comps;
        int y;
        do  {
            y = S.top(); S.pop();
            Gr[y] = comps;
            C.push_back(y);
            B[y] = 0;
        } while (y != x);
        for (const auto& node : C)
            for (const auto& f : Gx[node])
                if (Gr[node] != Gr[f] && Gr[f] != 0)
                    G[Gr[node]].push_back(Gr[f]);
        C.clear();
    }
};