Pagini recente » Cod sursa (job #1014946) | Cod sursa (job #1903797) | Cod sursa (job #1351032) | Cod sursa (job #2382275) | Cod sursa (job #1182296)
#include<stdio.h>
#include<stack>
#include<vector>
const int N=32000, LOG=17;
using namespace std;
FILE *f,*g;
stack<int> varfuri;
int n, m, q, index, root;
vector<int> graph[N], gdag[N], gdags[N];
bool viz[N], seen[N];
int deg[N]; int depth[N], updepth[N], comp[N];
int adanc[N], low[N][LOG+1], tata[N][LOG+1];
void Read(void){
f=fopen("obiective.in","r");
g=fopen("obiective.out","w");
fscanf(f,"%d%d",&n,&m);
int a,b;
for(int i=1;i<=m;i++){
fscanf(f,"%d%d",&a,&b);
graph[a].push_back(b);
}
fscanf(f,"%d",&q);
}
//Auxiliara MakeDAG
void DFSDAG(int v){
vector<int>::iterator it=graph[v].begin(); int aux;
seen[v]=1; updepth[v]=depth[v]; varfuri.push(v);
while(it != graph[v].end()){
if ( !seen[*it]){
depth[*it]=depth[v]+1;
DFSDAG(*it);
if (updepth[*it] == depth[*it]) {
index++;
while (varfuri.top() != v) {
aux=varfuri.top(); varfuri.pop();
comp[aux]=index;
}
}
else if (updepth[*it] < updepth[v]) updepth[v]=updepth[*it];
}
else if (updepth[*it] < updepth[v]) updepth[v]=updepth[*it];
it++;
}
}
//creeaza DAG
void MakeDAG(void){
int i; int aux;
for(i=1;i<=n;i++){
if (!seen[i]){
DFSDAG(i); index++;
while (!varfuri.empty()){
aux=varfuri.top(); varfuri.pop();
comp[aux]=index;
}
}
}
vector<int>::iterator it;
for(i=1; i<=n; i++) {
it=graph[i].begin();
while(it !=graph[i].end()){
if (comp[*it] != comp[i]) {
gdag[comp[i]].push_back(comp[*it]); gdags[comp[*it]].push_back(comp[i]);
deg[comp[*it]]++;
}
it++;
}
}
n=index;
}
//Gaseste radacina DAG (exsitenta && unica din ipoteza)
void FindRoot(void){
for(root=1;root<=n;root++) if (deg[root] == 0) return;
}
//Creeaza arborele de care ne folosim
void MakeArb(int v){
vector<int>::iterator it=gdag[v].begin(), itaux; viz[v]=1; low[v][0]=tata[v][0];
while (it != gdag[v].end()){
if (!viz[*it]){
adanc[*it]=adanc[v]+1; tata[*it][0]=v;
MakeArb(*it);
if (adanc[low[*it][0]] < adanc[low[v][0]]) low[v][0]=low[*it][0];
}
else if (adanc[low[*it][0]] < adanc[low[v][0]]) low[v][0]=low[*it][0];
it++;
}
itaux=gdags[v].begin();
while (itaux != gdags[v].end()){
if (adanc[*itaux] < adanc[low[v][0]]) low[v][0]=*itaux;
itaux++;
}
}
void PrepareLca(void){
for(int i=1;i<=LOG;i++)
for(int j=1;j<=n;j++)
if (tata[j][i-1] == root)
tata[j][i]=root;
else tata[j][i] = tata[tata[j][i-1]][i-1];
}
void PrepareLow(void){
for(int i=1;i<=LOG;i++)
for(int j=1;j<=n;j++)
if (adanc[low[j][i-1]] == 0)
low[j][i]=root;
else low[j][i] = low[low[j][i-1]][i-1];
}
//Auxiliara FindLCA
int Stramos(int v, int pasi){
int step=1, cnt=0;
while (step<=n) {step<<=1; cnt++;}
while (step){
if (step<=pasi){
v=tata[v][cnt];
pasi-=step;
}
step>>=1; cnt--;
}
return v;
}
//Auxiliara FindMin
int FindLCA(int v, int u){
if (adanc[v]<adanc[u]) swap(u,v);
v=Stramos(v,adanc[u]-adanc[v]);
if (u == v) return adanc[u];
int cnt=LOG+1;
while (cnt){
cnt--;
if (tata[v][cnt] != tata[u][cnt]){
v=tata[v][cnt], u=tata[u][cnt];
}
}
return adanc[v]-1;
}
//Auxiliara Solve
int FindMin(int v, int u){
int deep=FindLCA(v,u);
if (deep >= adanc[v]) return 0;
int cnt=LOG+1; int steps=0;
while (cnt){
cnt--;
if (adanc[low[v][cnt]] > deep) {
v=low[v][cnt]; steps = steps + (1<<cnt);
}
}
return steps+1;
}
void Solve(void){
int i, a,b;
for(i=1;i<=q;i++){
fscanf(f,"%d%d",&a,&b);
fprintf(g,"%d\n",FindMin(comp[a],comp[b]));
}
}
int main(void){
Read();
MakeDAG(); FindRoot(); MakeArb(root);
tata[root][0]=root; PrepareLca(); PrepareLow();
Solve();
return 0;
}