Pagini recente » Cod sursa (job #2066780) | Cod sursa (job #2035843) | Cod sursa (job #2316259) | Monitorul de evaluare | Cod sursa (job #1277620)
#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;
}