Pagini recente » Cod sursa (job #2529410) | Cod sursa (job #2475256) | Cod sursa (job #1573686) | Cod sursa (job #2169516) | Cod sursa (job #934036)
Cod sursa(job #934036)
#include <fstream>
#include <vector>
#include <algorithm>
#include <cstring>
#define lmax 16
#define nmax (1<<15)
#define Vecin(G) G[Nod][i]
using namespace std;
vector <int> G[nmax],Gt[nmax],Gs[nmax],Order;
int N,Q,CTC,Root,order,Component[nmax],Log2[nmax];
int 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 Nod) {
used[Nod]=true;
for(int i=0;i<Gs[Nod].size();i++)
if(!used[Vecin(Gs)]) {
DfsHighest(Vecin(Gs));
if(Level[Highest[0][Vecin(Gs)]] < Level[Highest[0][Nod]])
Highest[0][Nod] = Highest[0][Vecin(Gs)];
}
for(int i=1;Highest[i-1][ Highest[i-1][Nod] ];i++)
Highest[i][Nod] = Highest[i-1][ Highest[i-1][Nod] ];
}
void BuildHighest() {
int i,j,Nod;
for(Nod=1;Nod<=CTC;Nod++)
Highest[0][Nod]=Father[0][Nod];
for(Nod=1;Nod<=CTC;Nod++)
for(i=0;i<Gs[Nod].size();i++)
if(Level[Nod]<Level[Highest[0][Vecin(Gs)]])
Highest[0][Vecin(Gs)]=Nod;
memset(used,0,sizeof(used));
DfsHighest(Root);
for(i=1;i<lmax;i++)
for(j=1;j<=CTC;j++)
Highest[i][j] = Highest[i-1][ Highest[i-1][j] ];
}
void DfsFather(int Nod) {
used[Nod]=true;
for(int i=0;Father[i][ Father[i][Nod] ];i++)
Father[i+1][Nod] = Father[i][ Father[i][Nod] ];
for(int i=0;i<Gs[Nod].size();i++)
if(!used[Vecin(Gs)]) {
Father[0][Vecin(Gs)]=Nod;
Level[Vecin(Gs)]=Level[Nod]+1;
DfsFather(Vecin(Gs));
}
}
void BuildFather() {
int i;
for(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 SortareTopologica(int Nod) {
used[Nod]=true;
for(int i=0;i<Gs[Nod].size();i++)
if(!used[Vecin(Gs)])
SortareTopologica(Vecin(Gs));
Order[Nod]=++order;
}
void BuildNewG() {
int i,Nod;
memset(used,0,sizeof(used));
for(Nod=1;Nod<=N;Nod++)
for(i=0;i<G[Nod].size();i++)
if(Component[Nod] != Component[Vecin(G)]) {
Gs[Component[Nod]].push_back(Component[Vecin(G)]);
used[Component[Vecin(G)]]=true;
}
for(Nod=1;Nod<=CTC;Nod++)
if(!used[Nod]) {
Root=Nod;
break;
}
memset(used,0,sizeof(used));
SortareTopologica(Root);
for(Nod=1;Nod<=CTC;Nod++)
sort(Gs[Nod].begin(),Gs[Nod].end(),compare);
}
void DfsCtc(int Nod) {
Component[Nod]=CTC;
used[Nod]=true;
for(int i=0;i<Gt[Nod].size();i++)
if(!used[Vecin(Gt)])
DfsCtc(Vecin(Gt));
}
void SortareTopologicaK(int Nod) {
used[Nod]=true;
for(int i=0;i<G[Nod].size();i++)
if(!used[Vecin(G)])
SortareTopologicaK(Vecin(G));
Order.push_back(Nod);
}
void Kosaraju() {
int i,Nod;
for(Nod=1;Nod<=N;Nod++)
if(!used[Nod])
SortareTopologicaK(Nod);
memset(used,0,sizeof(used));
reverse(Order.begin(),Order.end());
for(i=CTC=0;i<Order.size();i++)
if(!used[Nod = Order[i]]) {
CTC++;
DfsCtc(Nod);
}
}
void read(ifstream & in) {
int x,y,M;
in>>N>>M;
while(M--) {
in>>x>>y;
G[x].push_back(y);
Gt[y].push_back(x);
}
in>>Q;
}
int main() {
int A,B,C;
ifstream in("obiective.in");
ofstream out("obiective.out");
read(in);
Kosaraju();
BuildNewG();
BuildFather();
BuildHighest();
while(Q--) {
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;
}