Cod sursa(job #1533285)

Utilizator filip.mihalutMihalut Filip filip.mihalut Data 22 noiembrie 2015 12:52:01
Problema Obiective Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.69 kb
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

#define Nmax 32768
#define Log 16
#define INF 0x3f3f3f3f
#define pb push_back
#define sz(a) (int)((a).size())

int n, m, ct, cnt, niv;
vector<int> lv1[Nmax], lv2[Nmax], lv[Nmax];
int comp[Nmax];
int v[Nmax];
int list[Nmax];
int lvl[Nmax], low[Nmax];
int h[2 * Nmax];
int pos[Nmax];
int ai[4 * Nmax];
int P[Nmax][Log];

void citire()
{
    int i, a, b;

    scanf("%d %d\n", &n, &m);
    for (i = 1; i <= m; ++i)
    {
        scanf("%d %d\n", &a, &b);
        lv1[a].pb(b);
        lv2[b].pb(a);
    }
}

void DF1(int nod)
{
    int i;

    v[nod] = 1;
    for (i = 0; i < sz(lv2[nod]); ++i)
        if (!v[lv2[nod][i]])
            DF1(lv2[nod][i]);

    list[++ct] = nod;
}

void DF2(int nod)
{
    int i;

    comp[nod] = ct;
    for (i = 0; i < sz(lv1[nod]); ++i)
        if (!comp[lv1[nod][i]])
            DF2(lv1[nod][i]);
}

void DF(int nod)
{
    int i;

    v[nod] = 1;
    if (lvl[low[nod]] > lvl[nod]) low[nod] = nod;
    h[++cnt] = lvl[nod];
    pos[nod] = cnt;

    for (i = 0; i < sz(lv[nod]); ++i)
        if (lvl[low[lv[nod][i]]] > lvl[nod]) low[lv[nod][i]] = nod;

    for (i = 0; i < sz(lv[nod]); ++i)
        if (!v[lv[nod][i]])
        {
            lvl[lv[nod][i]] = lvl[nod] + 1;
            DF(lv[nod][i]);
            if (lvl[low[lv[nod][i]]] < lvl[low[nod]]) low[nod] = low[lv[nod][i]];
            h[++cnt] = lvl[nod];
        }
}

void init(int nod, int st, int dr)
{
    if (st == dr)
        ai[nod] = h[st];
    else
    {
        int mij = (st + dr) / 2, fs = nod * 2, fd = nod * 2 + 1;

        init(fs, st, mij);
        init(fd, mij + 1, dr);

        ai[nod] = min(ai[fs], ai[fd]);
    }
}

void query(int nod, int st, int dr, int a, int b)
{
    if (a <= st && dr <= b)
        niv = min(niv, ai[nod]);
    else
    {
        int mij = (st + dr) / 2, fs = nod * 2, fd = nod * 2 + 1;

        if (a <= mij) query(fs, st, mij, a, b);
        if (mij < b) query(fd, mij + 1, dr, a, b);
    }
}

void solve()
{
    int i, j, k, a, b, sol;

    for (i = 1; i <= n; ++i)
        if (!v[i])
            DF1(i);

    reverse(list+1, list+n+1);

    for (ct = 0, i = 1; i <= n; ++i)
        if (!comp[list[i]])
        {
            ++ct;
            DF2(list[i]);
        }

    for (i = 1; i <= n; ++i)
        for (j = 0; j < sz(lv1[i]); ++j)
            if (comp[i] != comp[lv1[i][j]])
                lv[comp[i]].pb(comp[lv1[i][j]]);

    for (i = 1; i <= n; ++i)
        sort(lv[i].rbegin(), lv[i].rend());

    memset(low, 0, sizeof(low));
    memset(v, 0, sizeof(v));
    lvl[0] = INF;
    lvl[ct] = 1;

    DF(ct);
    init(1, 1, cnt);

    memset(P[ct], -1, sizeof(P[ct]));
    for (i = ct - 1; i >= 1; --i)
    {
        P[i][0] = low[i];
        for (j = 1; j < Log; ++j)
            if (P[i][j - 1] != -1 && P[P[i][j - 1]][j - 1] != -1)
                P[i][j] = P[P[i][j - 1]][j - 1];
            else
                P[i][j] = -1;
    }

    scanf("%d\n", &k);
    for (i = 1; i <= k; ++i)
    {
        scanf("%d %d\n", &a, &b);
        a = comp[a];
        b = comp[b];

        niv = INF;
        query(1, 1, cnt, min(pos[a], pos[b]), max(pos[a], pos[b]));

        sol = 0;
        for (j = Log - 1; j >= 0; --j)
            if (P[a][j] != -1 && lvl[P[a][j]] > niv)
            {
                a = P[a][j];
                sol += 1 << j;
            }
        if (lvl[a] > niv) ++sol;

        printf("%d\n", sol);
    }
}

int main()
{
    freopen("obiective.in", "r", stdin);
    freopen("obiective.out", "w", stdout);

    citire();
    solve();

    return 0;
}