Cod sursa(job #932040)

Utilizator dicu_dariaDaria Dicu dicu_daria Data 28 martie 2013 17:43:05
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.48 kb
#include <fstream>
#include <cstring>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#define mp make_pair

using namespace std;

vector <int> v[32010], vt[32010];
vector <int>G[32010], GT[32010], Nodes[32010];
int ST[32010], tata[32010], lowest[32010], Euler[800010], rmq[800010][20], Log[800010], Depth[32010], First[32010], Nod[800010], ctc[32010];
int t, n, m, i, x, y, root, nr, k, comp, c, j, a, b, lca, d1, d2;
bool viz[32010];
int level[32010], deg[32010], in[32010], out[32010];
stack <int> S;

bool ancestor(int a, int b)
{
    return in[a] <= in[b] and out[a] >= out[b];
}

bool cmp(int a, int b)
{
    return ST[a] < ST[b];
}

void SortareTopologica(int x)
{
    vector <int> :: iterator it;
    if(x == root) level[x] = 1;
    viz[x] = 1;
    for(it = v[x].begin(); it != v[x].end(); ++it)
        if(!viz[*it])
        {
            level[*it] = level[x] + 1;
            SortareTopologica(*it);
        }
    ST[x] = nr--;
}

void Liniarizare(int x, int level)
{
    vector <int> :: iterator it;
    Euler[++k] = level;
    Depth[x] = level;
    First[x] = k;
    Nod[k] = x;
    for(it = G[x].begin(); it != G[x].end(); ++it)
    if(!First[*it])
    {
        tata[*it] = x;
        Liniarizare(*it, level+1);
        Euler[++k] = level;
        Nod[k] = x;
    }
}

void GetLowest(int x)
{
    vector<int>::iterator it;
    viz[x] = 1;
    in[x] = ++t;
    if(x != root) lowest[x] = tata[x];
    for(it = v[x].begin(); it != v[x].end(); ++it)
    {
        if(!viz[*it])
        {
            tata[*it] = x;
            GetLowest(*it);
        }
        if(level[lowest[*it]] < level[lowest[x]]) lowest[x] = lowest[*it];
    }
    out[x] = ++t;
    for(it = vt[x].begin(); it != vt[x].end(); ++it)
        if(level[*it] < level[lowest[x]]) lowest[x] = *it;
}

void DF_back(int x)
{
    vector<int>::iterator it;
    Nodes[comp].push_back(x);
    ctc[x] = comp;
    for(it = GT[x].begin(); it != GT[x].end(); ++it)
        if(!ctc[*it]) DF_back(*it);
}

void DF(int x)
{
    vector<int>::iterator it;
    viz[x] = 1;
    for(it = G[x].begin(); it != G[x].end(); ++it)
        if(!viz[*it]) DF(*it);
    S.push(x);
}

int main()
{
    vector <int> :: iterator it, vec;
    ifstream fi("obiective.in");
    ofstream fo("obiective.out");
    fi >> n >> m;
    for(i = 1; i <= m; i++)
    {
        fi >> x >> y;
        G[x].push_back(y);
        GT[y].push_back(x);
    }
    for(i = 1; i <= n; i++) if(!viz[i]) DF(i);
    while(!S.empty())
    {
        while(!S.empty() and ctc[S.top()]) S.pop();
        if(S.empty()) break;
        comp++;
        DF_back(S.top());
    }
    for(i = 1; i <= comp; i++)
        for(it = Nodes[i].begin(); it != Nodes[i].end(); ++it)
        {
            for(vec = G[*it].begin(); vec != G[*it].end(); ++vec)
            if(ctc[*vec] != i)
            {
                deg[ctc[*vec]]++;
                v[i].push_back(ctc[*vec]);
            }
            for(vec = GT[*it].begin(); vec != GT[*it].end(); ++vec)
            if(ctc[*vec] != i)
            {
                vt[i].push_back(ctc[*vec]);
            }
        }
    for(i = 1; i <= comp; i++) if(!deg[i]) root = i;
    memset(viz, 0, sizeof(viz));
    for(i = 1, nr = comp; i <= comp; i++) if(!viz[i]) SortareTopologica(i);
    for(i = 1; i <= comp; i++) sort(v[i].begin(), v[i].end(), cmp);

    memset(viz, 0, sizeof(viz));
    GetLowest(root);

    for(i = 1; i <= n; i++) G[i].clear();
    for(i = 1; i <= n; i++) G[lowest[i]].push_back(i);

    Liniarizare(root, 1);

    for(i = 2; i <= k; i++) Log[i] = Log[i/2] + 1;
    for(i = 1; i <= k; i++) rmq[i][0] = i;
    for(c = 1; (1<<c) <= k; c++)
    {
        for(i = 1; i <= k; i++)
        {
            rmq[i][c] = rmq[i][c-1];
            j = i + (1<<(c-1));
            if(j <= k and Euler[rmq[j][c-1]] < Euler[rmq[i][c]]) rmq[i][c] = rmq[j][c-1];
        }
    }
    fi >> t;
    while(t--)
    {
        fi >> a >> b;
        a = ctc[a]; b = ctc[b];
        x = First[a]; y = First[b];
        if(x > y) swap(x, y);
        c = Log[y - x + 1];
        lca = rmq[x][c];
        j = y - (1<<c) + 1;
        if(Euler[lca] > Euler[rmq[j][c]]) lca = rmq[j][c];
        lca = Nod[lca];
        if(ancestor(a, b)) fo << "0\n"; else
        {
            if(!(ancestor(lca, a) and ancestor(lca, b))) lca = tata[lca];
            d1 = Depth[a] - Depth[lca];
            fo << d1 << "\n";
        }
    }
    return 0;
}