Pagini recente » Cod sursa (job #571111) | Monitorul de evaluare | Cod sursa (job #1377504) | Cod sursa (job #2300893) | Cod sursa (job #3303735)
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#define dim 32000
using namespace std;
ifstream fin ("obiective.in");
ofstream fout ("obiective.out");
struct mch
{
int x,y;
};
mch l[2*dim+1];
int n,m,knd,nrctc,nd[dim+1],ctc[dim+1],gr[dim+1],niv[dim+1],t[15][dim+1],nxt[15][dim+1];
bool vis[dim+1];
vector <int> vi[dim+1],vt[dim+1],vn[dim+1],v[dim+1],vnt[dim+1];
queue <int> q;
void read ()
{
fin>>n>>m;
for (int i=1; i<=m; i++)
{
fin>>l[i].x>>l[i].y;
vi[l[i].x].push_back (l[i].y);
vt[l[i].y].push_back (l[i].x);
}
}
void dfs1 (int nod)
{
vis[nod]=1;
for (int i=0; i<(int)vi[nod].size (); i++)
{
int vecin=vi[nod][i];
if (!vis[vecin])
dfs1 (vecin);
}
nd[++knd]=nod;
}
void dfs2 (int nod)
{
vis[nod]=1;
ctc[nod]=nrctc;
for (int i=0; i<(int)vt[nod].size (); i++)
{
int vecin=vt[nod][i];
if (!vis[vecin])
dfs2 (vecin);
}
}
void get_ctc ()
{
for (int i=1; i<=n; i++)
{
if (!vis[i])
dfs1 (i);
}
for (int i=1; i<=n; i++)
vis[i]=0;
for (int i=n; i>0; i--)
{
if (!vis[nd[i]])
{
nrctc++;
dfs2 (nd[i]);
}
}
for (int i=1; i<=n; i++)
vis[i]=0;
for (int i=1; i<=m; i++)
{
if (ctc[l[i].x]!=ctc[l[i].y])
{
vn[ctc[l[i].x]].push_back (ctc[l[i].y]);
vnt[ctc[l[i].y]].push_back (ctc[l[i].x]);
gr[ctc[l[i].y]]++;
}
}
n=nrctc;
for (int i=1; i<=n; i++)
sort (vn[i].begin (),vn[i].end ());
}
void dfs3 (int nod,int tt,int p)
{
niv[nod]=p;
vis[nod]=1;
t[0][nod]=tt;
for (int i=0; i<(int)vn[nod].size (); i++)
{
int vecin=vn[nod][i];
if (!vis[vecin])
{
v[nod].push_back (vecin);
dfs3 (vecin,nod,p+1);
}
}
}
void dfs4 (int nod)
{
nxt[0][nod]=nod;
for (int i=0; i<(int)vnt[nod].size (); i++)
{
int vecin=vnt[nod][i];
if (niv[vecin]<niv[nxt[0][nod]])
nxt[0][nod]=vecin;
}
for (int i=0; i<(int)v[nod].size (); i++)
{
int vecin=v[nod][i];
dfs4 (vecin);
if (niv[nxt[0][vecin]]<niv[nxt[0][nod]])
nxt[0][nod]=nxt[0][vecin];
}
}
void calc ()
{
for (int p=1; (1<<p)<=n; p++)
{
for (int i=1; i<=n; i++)
{
t[p][i]=t[p-1][t[p-1][i]];
nxt[p][i]=nxt[p-1][nxt[p-1][i]];
}
}
}
int get_lca (int x,int y)
{
if (niv[x]<niv[y])
swap (x,y);
int dif=niv[x]-niv[y];
for (int p=14; p>=0; p--)
{
if ((dif>>p)&1)
x=t[p][x];
}
for (int p=14; p>=0; p--)
{
if (t[p][x]!=t[p][y])
x=t[p][x],y=t[p][y];
}
if (x!=y)
x=t[0][x];
return x;
}
int calc (int d,int x)
{
int sol=0;
for (int p=14; p>=0; p--)
{
if (niv[nxt[p][x]]>d)
{
sol+=(1<<p);
x=nxt[p][x];
}
}
if (niv[x]>d)
sol++;
return sol;
}
void solve ()
{
int q,x,y;
fin>>q;
while (q--)
{
fin>>x>>y;
if (ctc[x]==ctc[y])
fout<<"0\n";
else
{
x=ctc[x];
y=ctc[y];
int p=get_lca (x,y);
fout<<calc (niv[p],x)<<"\n";
}
}
}
int main ()
{
/**
Facem graful ctc. Noul graf va fi un "arbore" (intr-un nod nu intra doua lanturi - nodurile vor fi pe un lant (res))
Fiecare nod din lant va fi conectat cu celelalte (au un nod la care se ajunge comun, fara cicli => o sort. top)
=> dintr-un nod pleaca mai multe lanturi.
Pt a det arborele si niv, sortam listele de muchii pt fiecare nod (primul nod din sort top din lista e un vecin - nu mai e niciun nod mai sus, apoi urmatorul nevizitat (nu e in subarb vecin))
Din x tb sa vedem nr minim de urcarii <=lca => nxt[0][nod]=niv min din nod (din muchiile spre el), il calculam + din vecini (coboara si apoi urca)
Facem bl
**/
read ();
get_ctc ();
dfs3 (1,0,1);
dfs4 (1);
calc ();
solve ();
return 0;
}