Cod sursa(job #931845)

Utilizator dicu_dariaDaria Dicu dicu_daria Data 28 martie 2013 15:20:24
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.9 kb
#include <fstream>
#include <stack>
#include <vector>
#include <utility>
#define mp make_pair

using namespace std;

vector < pair<int, int> > v[32010];
vector <int>G[32010], GT[32010], Nodes[32010];
int Euler[800010], rmq[800010][20], Log[800010], Depth[32010], First[32010], Nod[800010], Sum[32010], ctc[32010];
int t, n, m, i, x, y, k, comp, c, j, a, b, lca, d1, d2;
bool viz[32010];
stack <int> S;

void Liniarizare(int x, int level)
{
    vector<pair<int, int> > :: iterator it;
    Euler[++k] = level;
    Depth[x] = level;
    First[x] = k;
    Nod[k] = x;
    for(it = v[x].begin(); it != v[x].end(); ++it)
    if(!First[it->first])
    {
        Sum[it->first] = Sum[x];
        if(it->second) Sum[it->first]++;
        Liniarizare(it->first, level+1);
        Euler[++k] = level;
        Nod[k] = x;
    }
}

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) v[i].push_back(mp(ctc[*vec], 0));

            for(vec = GT[*it].begin(); vec != GT[*it].end(); ++vec)
                if(ctc[*vec] != i) v[i].push_back(mp(ctc[*vec], 1));
        }
    Liniarizare(1, 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];

        d1 = Depth[a] - Depth[lca] - (Sum[a] - Sum[lca]);
        d2 = Sum[b] - Sum[lca];
        fo << d1 + d2 << "\n";
    }
    return 0;
}