Cod sursa(job #1277620)

Utilizator okros_alexandruOkros Alexandru okros_alexandru Data 27 noiembrie 2014 21:57:34
Problema Obiective Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.03 kb
#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>

#define Lmax 16
#define Nmax 32100
#define Neighbour(Graph) Graph[Node][i]

using namespace std;

vector <int> Order, Graph[Nmax], GraphTr[Nmax], Tree[Nmax];
int N, nrComp, Top, Root, Component[Nmax], Log2[Nmax], Father[Lmax][Nmax], Level[Nmax], Highest[Lmax][Nmax];
bool used[Nmax];

int Query(int A, int B) {

    int Answer = 0, Step;

    for(Step = Log2[Level[A]] + 1; Step >= 0; Step--)
        if(Level[Highest[Step][A]] > Level[B]) {
            Answer += (1<<Step);
            A = Highest[Step][A];
            }

    return (Answer + 1);

}
int Lca(int A, int B) {

    for(; Level[A] > Level[B]; A = Father[Log2[Level[A] - Level[B]]][A]);
    for(; Level[B] > Level[A]; B = Father[Log2[Level[B] - Level[A]]][B]);

    for(int Step = Log2[Level[A]]; Step >= 0; Step--)
        if(Father[Step][A] != Father[Step][B]) {
            A = Father[Step][A];
            B = Father[Step][B];
        }

    if(A != B)
        A = Father[0][A];

    return A;

}
void dfsHighest(int Node) {

    used[Node] = true;

    for(int i = 0; i < Tree[Node].size(); i++)
        if(!used[Neighbour(Tree)]) {

            dfsHighest(Neighbour(Tree));

            if(Level[Highest[0][Neighbour(Tree)]] < Level[Highest[0][Node]])
                Highest[0][Node] = Highest[0][Neighbour(Tree)];
        }
}
void buildHighest() {

    int i, j, Node;

    for(Node = 1; Node <= nrComp; Node++)
        Highest[0][Node] = Father[0][Node];

    for(Node = 1; Node <= nrComp; Node++)
        for(i = 0; i < Tree[Node].size(); i++)
            if(Level[Node] < Level[ Highest[0][Neighbour(Tree)] ])
                Highest[0][Neighbour(Tree)] = Node;

    memset(used, 0, sizeof(used));

    dfsHighest(Root);

    for(i = 1; i < Lmax; i++)
        for(j = 1; j <= nrComp; j++)
            Highest[i][j] = Highest[i - 1][ Highest[i - 1][j] ];

}
void dfsFather(int Node) {

    int i;

    used[Node] = true;

    for(i = 0; Father[i][ Father[i][Node] ]; i++)
        Father[i + 1][Node] = Father[i][ Father[i][Node] ];

    for(i = 0; i < Tree[Node].size(); i++)
        if(!used[Neighbour(Tree)]) {

            Father[0][Neighbour(Tree)] = Node;
            Level[Neighbour(Tree)] = Level[Node] + 1;
            dfsFather(Neighbour(Tree));
        }
}
void buildFather() {

    for(int i = 2; i < Nmax; i++)
        Log2[i] = Log2[i >> 1] + 1;

    memset(used,0,sizeof(used));

    dfsFather(Root);

}
bool compare(int A, int B) {

    return Order[A] > Order[B];
}
void sortTopologicalTree(int Node) {

    used[Node] = true;

    for(int i = 0; i < Tree[Node].size(); i++)
        if(!used[Neighbour(Tree)])
            sortTopologicalTree(Neighbour(Tree));

    Order[Node] = ++Top;

}
void buildTree() {

    int i, Node;

    memset(used, 0, sizeof(used));

    for(Node = 1; Node <= N; Node++)
        for(i = 0; i < Graph[Node].size(); i++)
            if(Component[Node] != Component[Neighbour(Graph)]) {
                Tree[Component[Node]].push_back(Component[Neighbour(Graph)]);
                used[Component[Neighbour(Graph)]] = true;
            }

    for(Node = 1; Node <= nrComp; Node++)
        if(!used[Node]) {
            Root = Node;
            break;
        }

    memset(used, 0, sizeof(used));
    sortTopologicalTree(Root);

    for(Node = 1; Node <= nrComp; Node++)
        sort(Tree[Node].begin(), Tree[Node].end(), compare);

}
void dfsComponent(int Node) {

    used[Node] = true;
    Component[Node] = nrComp;

    for(int i = 0; i < GraphTr[Node].size(); i++)
        if(!used[Neighbour(GraphTr)])
            dfsComponent(Neighbour(GraphTr));

}
void sortTopological(int Node) {

    used[Node] = true;

    for(int i = 0; i < Graph[Node].size(); i++)
        if(!used[Neighbour(Graph)])
            sortTopological(Neighbour(Graph));

    Order.push_back(Node);
}
void Kosaraju() {

    int i;

    for(i = 1; i <= N; i++)
        if(!used[i])
            sortTopological(i);

    reverse(Order.begin(), Order.end());
    memset(used, 0, sizeof(used));

    for(i = 0; i < Order.size(); i++)
        if(!used[Order[i]]) {
            ++nrComp;
            dfsComponent(Order[i]);
        }
}
void Prepare() {

    Kosaraju();
    buildTree();
    buildFather();
    buildHighest();
}
void Read(ifstream & in) {

    int x, y, M;

    in >> N >> M;

    while(M--) {
        in >> x >> y;
        Graph[x].push_back(y);
        GraphTr[y].push_back(x);
    }
}
int main() {

    int queries, A, B, C;

    ifstream in("obiective.in");
    ofstream out("obiective.out");

    Read(in);
    Prepare();

    in >> queries;

    while(queries--) {

        in >> A >> B;

        A = Component[A];
        B = Component[B];

        C = Lca(A, B);

        if(C == A || A == B)
            out << "0\n";
        else
            out << Query(A, C) << '\n';

    }

    in.close();
    out.close();

    return 0;
}