Cod sursa(job #923436)

Utilizator cernat.catallinFMI Cernat Catalin Stefan cernat.catallin Data 23 martie 2013 16:18:25
Problema Obiective Scor 35
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.68 kb
#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

#define Nmax 32005
#define inf 100000

vector < vector<int> > graf, grafT;
int n, m, c, nrctc, t, s, d;
int visited[Nmax], forder[Nmax], ctc[Nmax], dist[Nmax];

void read(){
    int x, y;
    scanf("%i %i", &n, &m);
    graf.resize(n+1);
    grafT.resize(n+1);

    for(int i = 1; i <= m; ++i){
        scanf("%i %i", &x, &y);

        graf[x].push_back(y);
        grafT[y].push_back(x);
    }
}

int findD(int x, vector<int>& v){ // verific daca elementul x se afla in vectorul v
    int size = v.size(), i;
    for(i = 0; i < size; ++i)
        if(v[i] == x) return 1;
    return 0;
}

void dfsO(int v){ // stabilesc timpii terminali de cautare pentru dfs in graful initial
    int i, size;
    visited[v] = 1;

    for(i = 0, size = graf[v].size(); i < size; ++i)
        if(!visited[ graf[v][i] ])
            dfsO(graf[v][i]);

    forder[++c] = v;
}

void dfsT(int v){ // parcurg graful transpus pentru a gasi componentele tare conexe (kosaraju)
    int i, size;
    visited[v] = 0;
    ctc[v] = nrctc;

    for(i = 0, size = grafT[v].size(); i < size; ++i)
        if(visited[ grafT[v][i] ])
            dfsT( grafT[v][i] );
}

void bellman(){
    int at, size;
    queue<int> q;
    visited[s] = 1;
    dist[s] = 0;
    q.push(s);

    while(!q.empty()){
        at = q.front();
        q.pop();
        size = grafT[at].size();
        visited[at] = 0;

        for(int i = 0; i < size; ++i){
            if(grafT[at][i] < 0){ // muchie de la gratT[at][i] la at
                if(dist[ -grafT[at][i] ] > dist[at] + 1){
                    dist[ -grafT[at][i] ] = dist[at] + 1;
                    if(!visited[ -grafT[at][i] ]){
                        visited[ -grafT[at][i] ] = 1;
                        q.push( -grafT[at][i]);
                    }
                }
            }
            else{ // muchie de la at la grafT[at][i]
                if(dist[ grafT[at][i] ] > dist[at]){
                    dist[ grafT[at][i] ] = dist[at];
                    if(!visited[ grafT[at][i] ]){
                        visited[ grafT[at][i] ] = 1;
                        q.push(grafT[at][i]);
                    }
                }
            }
        }
    }
}

void solve(){

    for(int i = 1; i <= n ; ++i) // kosaraju
        if(!visited[i])
            dfsO(i);
    for(int i = n; i >= 1; --i) // kosaraju
        if(visited[ forder[i] ]){
            ++nrctc;
            dfsT(forder[i]);
        }
    for(int i = 1; i <= n; ++i) grafT[i].clear(); // reseteaza grafT

    for(int i = 1; i <= n; ++i) // grafT este graful componentelor conexe
        for(int j = 0, size = graf[i].size(); j < size; ++j)
            if(ctc[i] != ctc[ graf[i][j] ]){
                if(!findD(ctc[ graf[i][j] ], grafT[ ctc[i] ])) // verific daca am mai adaugat aceeasi muchie, in caz contrar o adaug
                    grafT[ ctc[i] ].push_back( ctc[ graf[i][j] ] );
                if(!findD(-ctc[i], grafT[ ctc[ graf[i][j] ] ]))
                    grafT[ ctc[ graf[i][j] ] ].push_back( -ctc[i] ); // daca vecinul este cu minus, muchia este de la vecin la nod
            }
    scanf("%i", &t);
    for(int ii = 1; ii <= t; ++ii){
        scanf("%i %i", &s, &d);
        s = ctc[s];
        d = ctc[d];
        for(int i = 1; i <= nrctc; ++i) visited[i] = 0;
        for(int i = 1; i <= nrctc; ++i) dist[i] = inf;
        bellman();
        printf("%i\n", dist[d]);
    }
}

int main(){
    freopen("obiective.in", "r", stdin);
    freopen("obiective.out", "w", stdout);

    read();
    solve();
    fclose(stdout);

    return 0;
}