Cod sursa(job #1828956)

Utilizator alexpetrescuAlexandru Petrescu alexpetrescu Data 14 decembrie 2016 09:18:10
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.68 kb
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cctype>

#define INF 1000000000

#define BUF_SIZE 1<<17

#define MAXN 32000
#define LOGN 14
#define MAXM 64000

std::vector <int> g1[MAXN]; //graful initial
std::vector <int> g2[MAXN]; //g1 intors
std::vector <int> g3[MAXN]; //arobrele

int l, t, k, ind[MAXN+1], c[MAXN+1], h[MAXN+1];
bool viz[MAXN+1];

int str[LOGN+1][MAXN+1], best[LOGN+1][MAXN+1];

int pos=BUF_SIZE;
char buf[BUF_SIZE];
FILE *fin;

inline char nextch(){
    if(pos==BUF_SIZE) fread(buf, BUF_SIZE, 1, fin), pos=0;
    return buf[pos++];
}

inline int read(){
    int x=0;
    char ch=nextch();
    while(!isdigit(ch)) ch=nextch();
    while(isdigit(ch)){
        x=10*x+ch-'0';
        ch=nextch();
    }
    return x;
}

void dfs1(int x){
    viz[x]=1;
    for(auto y:g1[x])
        if(!viz[y])
            dfs1(y);
    ind[++t]=x;
}

void dfs2(int x){
    c[x]=k;
    viz[x]=0;
    for(auto y:g2[x])
        if(viz[y])
            dfs2(y);
}

void dfs3(int x){
    viz[x]=1;
    for(auto y:g3[x]){
        if(viz[y]){
            if(h[x]<h[best[0][y]])
                best[0][y]=x;
        }else{
            str[0][y]=x;
            h[y]=h[x]+1;
            best[0][y]=x;
            dfs3(y);
        }
    }
}

void dfs4(int x){
    for(auto y:g3[x]){
        if(str[0][y]==x){
            dfs4(y);
            if(h[best[0][y]]<h[best[0][x]])
                best[0][x]=best[0][y];
        }
    }
}

void dfs5(int x){
    best[l][x]=best[l-1][best[l-1][x]];
    for(auto y:g3[x]){
        if(str[0][y]==x){
            dfs5(y);
            if(h[best[l][y]]<h[best[l][x]])
                best[l][x]=best[l][y];
        }
    }
}

inline int lca(int a, int b){
    if(h[a]>h[b]){
        int aux=a;
        a=b;
        b=aux;
    }

    for(int pas=LOGN; pas>=0; pas--)
        if(h[b]-h[a]>=(1<<pas))
            b=str[pas][b];

    if(a==b) return a;

    for(int pas=LOGN; pas>=0; pas--){
        if(str[pas][a]!=str[pas][b]){
            a=str[pas][a];
            b=str[pas][b];
        }
    }

    return str[0][a];
}

inline int dist(int a, int b){
    if(a==b) return 0;

    int ans=0;
    for(int pas=LOGN; pas>=0; pas--){
        if(h[b]<h[best[pas][a]]){
            ans+=1<<pas;
            a=best[pas][a];
        }
    }

    return ans+1;
}

int main(){
    FILE *fout;
    fin=fopen("obiective.in", "r");
    fout=fopen("obiective.out", "w");

    int n, m;
    n=read();
    m=read();
    for(int i=1; i<=m; i++){
        int x, y;
        x=read();
        y=read();

        g1[x].push_back(y);
        g2[y].push_back(x);
    }

    for(int i=1; i<=n; i++)
        if(!viz[i])
            dfs1(i);

    for(int i=n; i>0; i--){
        if(viz[ind[i]]){
            k++;
            dfs2(ind[i]);
        }
    }

    for(int i=1; i<=n; i++)
        for(auto x:g1[i])
            if(c[i]!=c[x])
                g3[c[i]].push_back(c[x]);

    for(int i=1; i<=k; i++){
        std::sort(g3[i].begin(), g3[i].end());
        std::vector<int>::iterator it=std::unique(g3[i].begin(), g3[i].end());
        g3[i].resize(std::distance(g3[i].begin(), it));
    }

    best[0][1]=0;
    dfs3(1);

    for(int i=1; (1<<i)<=k; i++)
        for(int j=1; j<=k; j++)
            str[i][j]=str[i-1][str[i-1][j]];

    dfs4(1);

    for(int i=1; (1<<i)<=k; i++){
        l=i;
        dfs5(1);
    }

    int q=read();
    for(; q; q--){
        int a, b;
        a=c[read()];
        b=c[read()];

        int u=lca(a, b);

        fprintf(fout, "%d\n", dist(a, u));
    }

    fclose(fin);
    fclose(fout);
    return 0;
}