Cod sursa(job #1182299)

Utilizator omerOmer Cerrahoglu omer Data 6 mai 2014 03:10:18
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.49 kb
#include<stdio.h>
#include<stack>
#include<vector>
const int N=32000, LOG=17;
using namespace std;
FILE *f,*g;

stack<int> varfuri;

int n, m, q, index, root;

vector<int> graph[N], gdag[N], gdags[N]; 

bool viz[N], seen[N];

int deg[N]; int depth[N], updepth[N], comp[N];

int adanc[N], low[N][LOG+1], tata[N][LOG+1];


void Read(void){

    f=fopen("obiective.in","r");
    g=fopen("obiective.out","w");

    fscanf(f,"%d%d",&n,&m);
    
    int a,b;
    for(int i=1;i<=m;i++){

        fscanf(f,"%d%d",&a,&b);
        graph[a].push_back(b);
    }

    fscanf(f,"%d",&q);
}

//Auxiliara MakeDAG
void DFSDAG(int v){
    
    vector<int>::iterator it=graph[v].begin(); int aux;
    seen[v]=1; updepth[v]=depth[v]; varfuri.push(v);
    
    while(it != graph[v].end()){

        if ( !seen[*it]){
            
            depth[*it]=depth[v]+1;
            DFSDAG(*it);

            if (updepth[*it] == depth[*it]) {
                
                index++;
                while (varfuri.top() != v) {
                    aux=varfuri.top(); varfuri.pop(); 
                    comp[aux]=index; 
                }
            }

            else if (updepth[*it] < updepth[v]) updepth[v]=updepth[*it];

        }

        else if (updepth[*it] < updepth[v]) updepth[v]=updepth[*it];

        it++;
    }
}

//creeaza DAG
void MakeDAG(void){

    int i; int aux;
    for(i=1;i<=n;i++){
        
        if (!seen[i]){
            
            DFSDAG(i); index++;
            
            while (!varfuri.empty()){
                aux=varfuri.top(); varfuri.pop();
                comp[aux]=index;
            }
        }
    }
    
    vector<int>::iterator it;
    for(i=1; i<=n; i++) {
        
        it=graph[i].begin();
        
        while(it !=graph[i].end()){
            
            if (comp[*it] != comp[i]) {
                gdag[comp[i]].push_back(comp[*it]); gdags[comp[*it]].push_back(comp[i]);
                deg[comp[*it]]++;
            }
            it++; 
        }
    }

    n=index;
}

//Gaseste radacina DAG (exsitenta && unica din ipoteza)
void FindRoot(void){

    for(root=1;root<=n;root++) if (deg[root] == 0) return;

}

//Creeaza arborele de care ne folosim
void MakeArb(int v){

    vector<int>::iterator it=gdag[v].begin(), itaux; viz[v]=1; low[v][0]=tata[v][0];

    while (it != gdag[v].end()){
        
        if (!viz[*it]){
            adanc[*it]=adanc[v]+1; tata[*it][0]=v;
            MakeArb(*it);
            
            if (adanc[low[*it][0]] < adanc[low[v][0]]) low[v][0]=low[*it][0];
        }

        else if (adanc[low[*it][0]] < adanc[low[v][0]]) low[v][0]=low[*it][0];
        
        it++;
    }

    itaux=gdags[v].begin();
    while (itaux != gdags[v].end()){
        if (adanc[*itaux] < adanc[low[v][0]]) low[v][0]=*itaux;
        itaux++;
    }
}

void PrepareLca(void){

    for(int i=1;i<=LOG;i++)
        for(int j=1;j<=n;j++)
            if (tata[j][i-1] == root) 
                tata[j][i]=root;
            else tata[j][i] = tata[tata[j][i-1]][i-1];

}

void PrepareLow(void){

    for(int i=1;i<=LOG;i++)
        for(int j=1;j<=n;j++)
            if (adanc[low[j][i-1]] == 0) 
                low[j][i]=root;
            else low[j][i] = low[low[j][i-1]][i-1];

}

//Auxiliara FindLCA
int Stramos(int v, int pasi){

    int step=1, cnt=0;
    while (step<=n) {step<<=1; cnt++;}
    while (step){
        if (step<=pasi){
            v=tata[v][cnt];
            pasi-=step;
        }
        step>>=1; cnt--;
    }
    return v;
}

//Auxiliara FindMin
int FindLCA(int v, int u){

    if (adanc[v]<adanc[u]) swap(u,v);
//    printf("%d %d %d %d %d %d ",adanc[v],adanc[u], tata[v][0],tata[v][1], v, u);
    v=Stramos(v,adanc[v]-adanc[u]);
   // printf("%d %d %d",v,u,adanc[u]);
    if (u == v) return adanc[u];

    int cnt=LOG+1;
    while (cnt){
        cnt--;
        if (tata[v][cnt] != tata[u][cnt]){
            v=tata[v][cnt], u=tata[u][cnt];
        }
        
    }
    return adanc[v]-1;

}

//Auxiliara Solve
int FindMin(int v, int u){

    int deep=FindLCA(v,u); 
    if (deep >= adanc[v]) return 0;

    int cnt=LOG+1; int steps=0;
    while (cnt){
        cnt--;
        if (adanc[low[v][cnt]] > deep) {
            v=low[v][cnt]; steps = steps + (1<<cnt);
        }
    }
    return steps+1;
}

void Solve(void){
    
    int i, a,b;

    for(i=1;i<=q;i++){
        
        fscanf(f,"%d%d",&a,&b);
        fprintf(g,"%d\n",FindMin(comp[a],comp[b]));
    }
}

int main(void){

    Read();

    MakeDAG(); FindRoot(); MakeArb(root);

    tata[root][0]=root; PrepareLca(); PrepareLow();

    Solve();

    return 0;
}