Cod sursa(job #1182485)

Utilizator omerOmer Cerrahoglu omer Data 6 mai 2014 16:52:45
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.54 kb
#include<stdio.h>
#include<stack>
#include<vector>
#include<algorithm>
const int N=33000;
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], tata[N];


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]) {
                
                comp[*it]=++index;;
                while (varfuri.top() != *it) {
                    aux=varfuri.top(); varfuri.pop(); 
                    comp[aux]=index; 
                }
                varfuri.pop();
               
            }

            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); if (!varfuri.empty()) 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]=tata[v];

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

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

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

int Stramos(int v, int pasi){
    
    while(pasi){
        v=tata[v];
        pasi--;
    }
    return v;
}

int FindLCA(int v, int u){
    
    if (adanc[v] < adanc[u]) swap(u,v);
    v=Stramos(v,adanc[v]-adanc[u]);

    if (u == v) return adanc[u];

    while (u != v){
        u=tata[u], v=tata[v];
    }

    return adanc[u];
}

int FindMin(int v, int u){

    int deep=FindLCA(v,u);
    int cnt=0;
    while (deep < adanc[v]){
        v=low[v], cnt++;
    }
    return cnt;
}

void Solve(void){
    
    int a,b;
    for(int 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(); tata[root]=root; MakeArb(root);
    
    Solve();

    return 0;
}