Cod sursa(job #872527)

Utilizator valentin.harsanValentin Harsan valentin.harsan Data 6 februarie 2013 10:17:55
Problema Obiective Scor 5
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.96 kb
#include<algorithm>
#include<fstream>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<cstring>
using namespace std;

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

const int N = 33000;
const int M = 63000;

int nr, n, m, t, a[M], b[M];
vector<int> v[N];
bool ver[N];

//CTC
int nrcomp, o[N], grad[N], rad;
map<int, int> conv;
set<pair<int, int> > temp;
vector<int> g[N], vt[N];

void df_ordine(int nod) {
    ver[nod] = 1;

    for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it)
        if(!ver[*it])
            df_ordine(*it);
    o[++nr] = nod;
}

void dfctc(int nod) {
    ver[nod] = 1;
    conv[nod] = nrcomp;

    for(vector<int>::iterator it = vt[nod].begin(); it != vt[nod].end(); ++it) if(!ver[*it])
        dfctc(*it);
}

void ctc() {
    int i;

    for(i = 1; i<=n; ++i) if(!ver[i])
        df_ordine(i);

    memset(ver, 0, sizeof(ver));
    for(i = n; i; --i) if(!ver[o[i]]) {
        ++nrcomp;
        dfctc(o[i]);
    }

    for(i = 1; i<=m; ++i) {

        int ca = conv[a[i]], cb = conv[b[i]];
        if(ca != cb && temp.find(pair<int, int>(ca, cb)) == temp.end()) {
            g[ca].push_back(cb), grad[cb]++;
            temp.insert(pair<int, int>(ca, cb));
        }
    }
}

//sortare topologica si sortarea muchiilor
int so[N], poz[N];

bool cmp(int nod1, int nod2) {
    return poz[nod1] < poz[nod2];
}

void topsort() {
    int i;
    queue<int> q;

    for(i = 1; i<=nrcomp; ++i) if(!grad[i]) {
        q.push(i);
        rad = i;
        break;
    }

    nr = 0;
    while(!q.empty()) {
        int el = q.front();
        q.pop();
        so[++nr] = el;
        poz[el] = nr;

        for(vector<int>::iterator it = g[el].begin(); it != g[el].end(); ++it) {
            grad[*it]--;

            if(!grad[*it])
                q.push(*it);
        }
    }

    for(i = 1; i<=nrcomp; ++i) if(g[i].size())
        sort(g[i].begin(), g[i].end(), cmp);
}

//liniarizarea arborelui
int cs[N], cd[N];

bool isAnc(int x, int y) {
    return (cs[y] <= cs[x] && cd[y] >= cd[x]);
}

void dfsE(int nod) {
    ver[nod] = 1;

    cs[nod] = ++nr;

    for(vector<int>::iterator it = g[nod].begin(); it != g[nod].end(); ++it) if(!ver[*it])
        dfsE(*it);
    cd[nod] = nr;
}

//calc nivmax
int niv[N], nivmax[19][N], el[19][N];

void dfsNiv(int nod) {
    ver[nod] = 1;

    for(vector<int>::iterator it = g[nod].begin(); it != g[nod].end(); ++it) {
        if(!ver[*it]) {
            niv[*it] = niv[nod] + 1;
            nivmax[0][*it] = niv[nod];
            el[0][*it] = nod;
            dfsNiv(*it);
        }
        else {
            if(nivmax[0][*it] > niv[nod])
                el[0][*it] = nod;

            nivmax[0][*it] = min(nivmax[0][*it], niv[nod]);
        }
    }
}

void calcStramosi() {
    int i, j;

    memset(ver, 0, sizeof(ver));
    dfsNiv(rad);

    for(i = 1; i < 19; ++i)
        for(j = 1; j <= nrcomp; ++j) {

            nivmax[i][j] = nivmax[i - 1][nivmax[i - 1][j]];
            el[i][j] = el[i - 1][el[i - 1][j]];
        }
}

int main() {
    int i, n1, n2, j, nod, sol;
    cs[0] = 0;
    cd[0] = 1000000000;

    in >> n >> m;

    for(i = 1; i<=m; ++i) {
        in >> a[i] >> b[i];
        v[a[i]].push_back(b[i]);

        vt[b[i]].push_back(a[i]);
    }

    ctc();

    topsort();

    memset(ver, 0, sizeof(ver)); nr = 0;
    dfsE(rad);

    calcStramosi();

    in >> t;

    for(i = 1; i<=t; ++i) {

        in >> n1 >> n2;
        n1 = conv[n1]; n2 = conv[n2];

        if(n1 == n2 || isAnc(n2, n1)) {
            out << 0 << "\n";
            continue;
        }

        nod = n1;
        sol = 0;
        for(j = 18; j >= 0; --j)
            if(!isAnc(n2, el[j][nod]))
                nod = el[j][nod], sol += (1<<j);

        if(isAnc(n2, el[0][nod]))
            ++sol;
        out << sol << "\n";
    }

    return 0;
}