Pagini recente » Cod sursa (job #2383383) | Cod sursa (job #946900) | Cod sursa (job #1515168) | Cod sursa (job #678409) | Cod sursa (job #1044833)
#include <fstream>
#include <vector>
#include <algorithm>
#include <stack>
#define NM 32010
#define LOGM 16
using namespace std;
ifstream f("obiective.in");
ofstream g("obiective.out");
int N, C, M, T, K;
int Level[NM], MinLevel[NM];
int WComponent[NM];
bool InStack[NM], NotRoot[NM];
vector<int> GI[NM], G[NM], GInverse[NM];
stack<int> S;
int Ancestors[LOGM][NM], UpMost[LOGM][NM];
int Depth[NM], MinDepth[NM];
void Read ()
{
f >> N >> M;
for (int i=1; i<=M; i++)
{
int a, b;
f >> a >> b;
GI[a].push_back(b);
}
}
void DoTarjan (int node)
{
MinLevel[node]=Level[node]=++K;
S.push(node);
InStack[node]=1;
for (vector<int>::iterator it=GI[node].begin(); it!=GI[node].end(); ++it)
if (!Level[*it])
{
DoTarjan(*it);
MinLevel[node]=min(MinLevel[node], MinLevel[*it]);
}
else
{
if (InStack[*it])
MinLevel[node]=min(MinLevel[node], MinLevel[*it]);
}
if (MinLevel[node]==Level[node])
{
++C;
for (; !S.empty(); )
{
int cnode=S.top();
WComponent[cnode]=C;
S.pop();
InStack[cnode]=0;
if (cnode==node)
break;
}
}
}
void CTC ()
{
for (int i=1; i<=N; i++)
if (!Level[i])
DoTarjan(i);
for (int i=1; i<=N; i++)
for (vector<int>::iterator it=GI[i].begin(); it!=GI[i].end(); ++it)
if (WComponent[i]!=WComponent[*it])
{
G[WComponent[i]].push_back(WComponent[*it]);
NotRoot[WComponent[*it]]=1;
}
for (int i=1; i<=C; i++)
{
sort(G[i].begin(), G[i].end());
G[i].resize(unique(G[i].begin(), G[i].end())-G[i].begin());
for (vector<int>::iterator it=G[i].begin(); it!=G[i].end(); ++it)
GInverse[*it].push_back(i);
}
}
void DFInverse (int node)
{
int pos=0;
MinDepth[node]=NM;
for (vector<int>::iterator it=GInverse[node].begin(); it!=GInverse[node].end(); ++it)
{
if (!Depth[*it])
DFInverse(*it);
if (Depth[*it]>Depth[node])
{
Depth[node]=Depth[*it];
pos=*it;
}
MinDepth[node]=min(MinDepth[node], MinDepth[*it]);
}
if (MinDepth[node]==NM)
MinDepth[node]=0;
MinDepth[node]++;
Depth[node]++;
Ancestors[0][node]=pos;
}
void DF (int node)
{
for (vector<int>::iterator it=G[node].begin(); it!=G[node].end(); ++it)
{
if (!UpMost[0][*it])
DF(*it);
if (Depth[UpMost[0][*it]]<Depth[UpMost[0][node]])
UpMost[0][node]=UpMost[0][*it];
}
for (vector<int>::iterator it=GInverse[node].begin(); it!=GInverse[node].end(); ++it)
if (Depth[*it]<Depth[UpMost[0][node]])
UpMost[0][node]=*it;
}
void BuildAncestors ()
{
for (int i=1; i<=C; i++)
if (!Depth[i])
DFInverse(i);
Depth[0]=NM;
for (int i=1; i<=C; i++)
if (!UpMost[0][i])
DF(i);
for (int j=1; (1 << j)<=C; j++)
for (int i=1; i<=C; i++)
{
Ancestors[j][i]=Ancestors[j-1][Ancestors[j-1][i]];
UpMost[j][i]=UpMost[j-1][UpMost[j-1][i]];
}
}
int LCA (int a, int b)
{
if (Depth[a]>Depth[b])
swap(a, b);
int log1, log2, k;
for (log1=0; (1 << log1)<Depth[a]; ++log1);
for (log2=0; (1 << log2)<Depth[b]; ++log2);
for (k=log2; k>=0; k--)
if (Depth[b]-(1 << k)>=Depth[a])
b=Ancestors[k][b];
if (a==b) return a;
for (k=log1; k>=0; k--)
if (Ancestors[k][a]!=0 && Ancestors[k][a]!=Ancestors[k][b])
{
a=Ancestors[k][a];
b=Ancestors[k][b];
}
return Ancestors[0][a];
}
int GetDist (int a, int t)
{
if (Depth[a]<=Depth[t])
return 0;
int ret=0, k, log;
for (log=0; (1 << log)<Depth[a]; ++log);
for (k=log; k>=0; k--)
if (UpMost[k][a] && Depth[UpMost[k][a]]>Depth[t])
{
a=UpMost[k][a];
ret+=1 << k;
}
if (Depth[a]>Depth[t])
ret++;
return ret;
}
void Solve ()
{
Depth[0]=0;
for (f >> T; T>=1; T--)
{
int a, b, c;
f >> a >> b;
a=WComponent[a];
b=WComponent[b];
c=LCA(a, b);
g << GetDist(a, c) << '\n';
}
}
int main ()
{
Read();
CTC();
BuildAncestors();
Solve();
f.close();
g.close();
return 0;
}