Cod sursa(job #918463)

Utilizator apopeid13Apopeid Alejandro apopeid13 Data 18 martie 2013 21:42:01
Problema Obiective Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 4.22 kb
#include <cstring>
#include <fstream>
#include <algorithm>
#include <set>
#include <vector>
 
using namespace std;
 
int N, M, TS;
vector<int> V[32002], P[32002], Q[32002];
set<int> W[32002];
int nodv[32002], minv[32002], where[32002], comps;
int T[32002], Tn[32002], in[32002], out[32002], timp;
int level[32002], lowest[32002];
int str[32002][16];
bool S[32002];
int ST[32002], STP[32002], K[32002];
 
class compare
{
    public: inline bool operator () (const int& i1, const int& i2)
    {
        return K[i1] < K[i2];
    }
};
 
inline bool is_str(int x, int y)
{
    return in[x] <= in[y] && out[x] >= out[y];
}
 
void Tarjan(int x)
{
    S[x] = true;
    nodv[x] = ++nodv[0];
    minv[x] = nodv[x];
    ST[++ST[0]] = x;
     
    for (vector<int>::iterator it = V[x].begin(); it != V[x].end(); ++it)
    {
        if (!S[*it]) Tarjan(*it);
        if (where[*it] == 0) minv[x] = min(minv[x], minv[*it]);
    }
     
    if (nodv[x] == minv[x])
    {
        ++comps;
        while (ST[ST[0]] != x)
        {
            where[ST[ST[0]]] = comps;
            --ST[0];
        }
        where[ST[ST[0]]] = comps;
        --ST[0];
    }
}
void sortT(int x)
{
    S[x] = true;
    for (set<int>::iterator it = W[x].begin(); it != W[x].end(); ++it)
        if (!S[*it])
            sortT(*it);
    ST[++ST[0]] = x;
}
void Dfs(int x)
{
    S[x] = true;
     
    in[x] = ++timp;
    if (x != ST[ST[0]])
        lowest[x] = Tn[x];
     
    for (vector<int>::iterator it = P[x].begin(); it != P[x].end(); ++it)
    {
        if (!S[*it])
        {
            Tn[*it] = x;
            level[*it] = level[x] + 1;
            Dfs(*it);
             
            if (x != ST[ST[0]])
                if (level[lowest[*it]] < level[lowest[x]])
                    lowest[x] = lowest[*it];
        }
         
        if (x != ST[ST[0]])
            if (level[*it] < level[lowest[x]])
                lowest[x] = *it;
    }
     
    out[x] = ++timp;
}
void goDfs(int x)
{
    STP[++STP[0]] = x;
    for (vector<int>::iterator it = Q[x].begin(); it != Q[x].end(); ++it)
    {
        T[*it] = x;
        goDfs(*it);
    }
    --STP[0];
     
    for (int i = 0; i <= 15; ++i)
    {
        if (STP[0] >= (1 << i)) str[x][i] = STP[STP[0] - (1 << i) + 1];
        else                    str[x][i] = ST[ST[0]];
    }
}
 
int main()
{
    ifstream fin("obiective.in");
    ofstream fout("obiective.out");
     
    fin >> N >> M;
    for (int i = 1, nod1, nod2; i <= M; ++i)
    {
        fin >> nod1 >> nod2;
        V[nod1].push_back(nod2);
    }
    for (int i = 1; i <= N; ++i)
        if (!S[i])
            Tarjan(i);
     
    for (int i = 1; i <= N; ++i)
        for (vector<int>::iterator it = V[i].begin(); it != V[i].end(); ++it)
            if (where[*it] != where[i])
                W[where[i]].insert(where[*it]);
     
    memset(S, 0, sizeof(S));
    ST[0] = 0;
     
    for (int i = 1; i <= comps; ++i)
        if (!S[i])
            sortT(i);
     
    for (int i = ST[0]; i >= 1; --i)
        K[ST[i]] = ST[0] - i + 1;
     
    for (int i = 1; i <= comps; ++i)
    {
        for (set<int>::iterator it = W[i].begin(); it != W[i].end(); ++it)
        {
            P[i].push_back(*it);
            P[*it].push_back(i);
        }
        sort(P[i].begin(), P[i].end(), compare());
    }
     
    memset(S, 0, sizeof(S));
    Dfs(ST[ST[0]]);
     
    for (int i = 1; i <= comps; ++i)
        if (lowest[i] != 0)
            Q[lowest[i]].push_back(i);
     
    goDfs(ST[ST[0]]);
     
    fin >> TS;
    for (int i = 1, nod1, nod2; i <= TS; ++i)
    {
        fin >> nod1 >> nod2;
        nod1 = where[nod1], nod2 = where[nod2];
         
        if (is_str(nod1, nod2)) fout << 0 << '\n';
        else
        {
            int nodnow = nod1, steps = 0;
            for (int j = 15; j >= 0; --j)
                if (!is_str(str[nodnow][j], nod2))
                {
                    nodnow = str[nodnow][j];
                    steps += (1 << j);
                }
            nodnow = T[nodnow];
            ++steps;
             
            fout << steps << '\n';
        }
    }
     
    fin.close();
    fout.close();
}