Cod sursa(job #2332724)

Utilizator refugiatBoni Daniel Stefan refugiat Data 31 ianuarie 2019 09:47:47
Problema Obiective Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.25 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
ifstream si("obiective.in");
ofstream so("obiective.out");
const int nmax=32e3;
const int logmax=14;
const int inf=1<<30;
int n, nrc, rad;
bool viz[nmax+1], grnenul[nmax+1];
int comp[nmax+1];
vector<int> ord, g[2][nmax+1];

int h[nmax+1], link[nmax+1];
int d[logmax+1][nmax+1];
int l[logmax+1][nmax+1];

vector<int> gc[nmax+1];

void dfs_ctc(int nod, int ind) {
    viz[nod]=1;
    if(ind==1)
        comp[nod]=nrc;

    for(auto i: g[ind][nod]) {
        if(viz[i]==0) {
            dfs_ctc (i, ind);
        }
    }

    if(ind==0)
        ord.push_back(nod);
}

void ctc() {
    for(int i=1; i<=n; ++i) {
        if(viz[i]==0)
            dfs_ctc(i, 0);
    }

    memset(viz, 0, sizeof(viz));
    reverse(ord.begin(), ord.end());

    for(auto i: ord) {
        if(viz[i]==0) {
            ++nrc;
            dfs_ctc(i, 1);
        }
    }
}

void trage_muchii_ctc() {
    for(int i=1; i<=n; ++i) {
        for(auto j: g[0][i]) {
            if(comp[i]!=comp[j]) {
                gc[comp[i]].push_back(comp[j]);
                grnenul[comp[j]]=1;
            }
        }
    }
    for(int i=1;i<=nrc; ++i) {
        sort(gc[i].begin(), gc[i].end());
        gc[i].erase(unique(gc[i].begin(), gc[i].end()), gc[i].end());

        if(grnenul[i]==0)
            rad=i;
    }
}

void dfs(int nod) {
    viz[nod]=1;
    for(auto i: gc[nod]) {
        if(link[i]==0||h[link[i]]>h[nod]) {
            link[i]=nod;
        }
    }
    for(auto i: gc[nod]) {
        if(viz[i]==0) {
            d[0][i]=nod;
            h[i]=h[nod]+1;
            dfs(i);
            if(link[nod]==0|| h[link[nod]]>h[link[i]]) {
                link[nod]=link[i];
            }
        }
    }
}

void precalc() {
    for(int i=1; (1<<i)<=nrc; ++i) {
        for(int j=1; j<=nrc; ++j) {
            d[i][j]=d[i-1][d[i-1][j]];
        }
    }
    for(int i=1;i<=nrc; ++i)
        l[0][i]=link[i];

    for(int i=1; (1<<i)<=nrc; ++i) {
        for(int j=1; j<=nrc; ++j) {
            l[i][j]=l[i-1][l[i-1][j]];
        }
    }
}

int lca_query(int x, int y) {
    if(h[x]>h[y])
        swap(x, y);
    int dif=h[y]-h[x];
    for(int i=logmax; i>=0; --i) {
        if(dif&(1<<i))
            y=d[i][y];
    }
    for(int i=logmax; i>=0; --i) {
        if(d[i][x]!=d[i][y]) {
           x=d[i][x];
            y=d[i][y];
        }
    }
    if(x!=y)
       x=d[0][x];
    return x;
}

int main() {
    int m;
    si>>n>>m;

    for(int i=1;i<=m; ++i) {
        int x, y;
        si>>x>>y;
        g[0][x].push_back(y);
        g[1][y].push_back(x);
    }
    ctc();
    trage_muchii_ctc();
    memset(viz, 0, sizeof(viz));
    dfs(rad);
    precalc();
    int t;
    si>>t;
    for(int i=1; i<=t; ++i) {
        int x, y;
        si>>x>>y;
        x=comp[x];
        y=comp[y];
        int lim=h[lca_query(x, y)];
        int ans=0;
        for(int j=logmax; j>=0; --j) {
            if(h[l[j][x]]>lim) {
                x=l[j][x];
                ans+=(1<<j);
            }
        }
        if(h[x]>lim)
            ++ans;
        so<<ans<<'\n';
    }
    return 0;
}