Pagini recente » Cod sursa (job #2158290) | Cod sursa (job #2826839) | Cod sursa (job #698658) | Cod sursa (job #1818654) | Cod sursa (job #690439)
Cod sursa(job #690439)
#include <fstream>
#include <vector>
#include <algorithm>
#define NMAx 32768
#define LMAx 16
#define pb push_back
using namespace std;
vector <int> G[NMAx],GT[NMAx];
int color,viz[NMAx],COMP[NMAx],GR_INT[NMAx];
int n,Teste,nr,CTC,RAD,t_OUT[NMAx],t_IN[NMAx];
int T[LMAx][NMAx],NIVEL[NMAx],LOG2[NMAx],Highest[NMAx];
int GET_HIGH[LMAx][NMAx],DEPTH[NMAx];
bool stramos(int X,int Y) {
return t_IN[X]<=t_IN[Y]&&t_OUT[Y]<=t_OUT[X];
}
int LCA(int X,int Y) {
while(NIVEL[X]>NIVEL[Y])
X=T[ LOG2[NIVEL[X] - NIVEL[Y]] ][X];
while(NIVEL[Y]>NIVEL[X])
Y=T[ LOG2[NIVEL[Y] - NIVEL[X]] ][Y];
if(X==Y)
return X;
for(int LG=LOG2[NIVEL[X]];LG>=0;LG--)
if(T[LG][X]!=T[LG][Y]) {
X=T[LG][X];
Y=T[LG][Y];
}
if(X!=Y)
X=T[0][X];
return X;
}
void sortare_topologica3(int nod) {
viz[nod]=color;
t_IN[nod]=++nr;
for(int i=0;i<GT[nod].size();i++)
if(viz[GT[nod][i]]!=color)
sortare_topologica3(GT[nod][i]);
t_OUT[nod]=++nr;
}
void DFS_GH(int nod) {
int i,vecin;
viz[nod]=color;
for(i=0;GET_HIGH[i][ GET_HIGH[i][nod] ];i++)
GET_HIGH[i+1][nod]=GET_HIGH[i][ GET_HIGH[i][nod] ];
for(i=0;i<G[nod].size();i++)
if(viz[vecin = G[nod][i]]!=color) {
GET_HIGH[0][vecin]=nod;
DEPTH[vecin]=DEPTH[nod]+1;
DFS_GH(vecin);
}
}
void DFS_H(int nod) {
int vecin;
viz[nod]=color;
for(int i=0;i<GT[nod].size();i++)
if(viz[vecin = GT[nod][i]]!=color) {
DFS_H(vecin);
if(NIVEL[Highest[vecin]]<NIVEL[Highest[nod]])
Highest[nod]=Highest[vecin];
}
}
void DFS_T(int nod) {
int i,vecin;
viz[nod]=color;
for(i=0;T[i][ T[i][nod] ];i++)
T[i+1][nod]=T[i][ T[i][nod] ];
for(i=0;i<GT[nod].size();i++)
if(viz[vecin = GT[nod][i]]!=color) {
T[0][vecin]=nod;
NIVEL[vecin]=NIVEL[nod]+1;
DFS_T(vecin);
}
}
bool cmp(int a,int b) {
return t_OUT[a]>t_OUT[b];
}
void sortare_topologica2(int nod) {
viz[nod]=color;
for(int i=0;i<GT[nod].size();i++)
if(viz[GT[nod][i]]!=color)
sortare_topologica2(GT[nod][i]);
t_OUT[nod]=++nr;
}
void DFS_CTC(int nod) {
COMP[nod]=CTC;
viz[nod]=color;
for(int i=0;i<GT[nod].size();i++)
if(viz[GT[nod][i]]!=color)
DFS_CTC(GT[nod][i]);
}
void sortare_topologica(int nod) {
viz[nod]=color;
for(int i=0;i<G[nod].size();i++)
if(viz[G[nod][i]]!=color)
sortare_topologica(G[nod][i]);
t_OUT[nr--]=nod;
}
int main() {
int i,j,x,y,m,nod,vecin,A,B,C,LG;
ifstream in("obiective.in");
ofstream out("obiective.out");
in>>n>>m;
// citire si creare G si GT
for(i=0;i<m;i++) {
in>>x>>y;
G[x].pb(y);
GT[y].pb(x);
}
// determinare CTC cu Kosaraju
for(i=1,color++,nr=n;i<=n;i++)
if(viz[i]!=color)
sortare_topologica(i);
for(i=1,color++;i<=n;i++)
if(viz[t_OUT[i]]!=color) {
++CTC;
DFS_CTC(t_OUT[i]);
}
// creare G* (in GT) cu muchii intre CTC
for(i=1;i<=n;i++)
GT[i].clear();
for(i=1;i<=n;i++)
for(j=0;j<G[i].size();j++)
if(COMP[i]!=COMP[vecin = G[i][j]]) {
GT[COMP[i]].pb(COMP[vecin]);
GR_INT[COMP[vecin]]++;
}
n=CTC;
// Determinare radacina G* (nodul cu grad de intrare 0)
for(i=1;i<=n&&!RAD;i++)
if(!GR_INT[i])
RAD=i;
// Sortare topologica pt G* din radacina
color++;
nr=0;
sortare_topologica2(RAD);
// Se sorteaza listele de adiacenta pt G* conform sortarii topologice
for(i=1;i<=n;i++)
sort(GT[i].begin(),GT[i].end(),cmp);
// Se construieste vectorul de tati (puteri alui 2)
color++;
DFS_T(RAD);
// Se construieste vectorul LOG2
for(i=2;i<NMAx;i++)
LOG2[i]=LOG2[i/2]+1;
// Se construieste Highest[i] cea mai mare inaltime la care poate ajunge nodul i cu cost 1
for(i=1;i<=n;i++)
Highest[i]=T[0][i];
for(nod=1;nod<=n;nod++)
for(j=0;j<GT[nod].size();j++)
if(T[0][vecin = GT[nod][j]]!=nod)
if(NIVEL[nod]<NIVEL[Highest[vecin]])
Highest[vecin]=nod;
color++;
DFS_H(RAD);
// Se construieste arborul final (in G)
for(i=1;i<=n;i++)
G[i].clear();
for(i=1;i<=n;i++)
if(Highest[i])
G[Highest[i]].pb(i);
// Se construieste vectorul GET_HIGH ?
color++;
DFS_GH(RAD);
// Sortare topologica pt arbore final
color++;
nr=0;
sortare_topologica3(RAD);
// rezolvarea ofertelor
in>>Teste;
for(i=1;i<=Teste;i++) {
in>>A>>B;
A=COMP[A];
B=COMP[B];
if(A==B) {
out<<"0\n";
continue;
}
C=LCA(A,B);
if(C==A) {
out<<"0\n";
continue;
}
B=A;
for(LG=LOG2[DEPTH[A]];LG>=0;LG--) {
if(!GET_HIGH[LG][A]) continue;
if(stramos(GET_HIGH[LG][A],C)) continue;
A=GET_HIGH[LG][A];
}
out<<(DEPTH[B]-DEPTH[A]+1)<<'\n';
}
in.close();
out.close();
return 0;
}