Pagini recente » Problema satisfiabilității formulelor logice de ordinul doi | Cod sursa (job #175440) | Problema satisfiabilităţii formulelor logice de ordinul doi | Autentificare | Cod sursa (job #2978049)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("obiective.in");
ofstream fout("obiective.out");
typedef pair<int,int> pii;
int n,m,root;
int comp[32005],nrcomp;
vector<int> st;
pii g[32005];
vector<int> muchii[32005],inv[32005];
int par[32005];
int in[32005],out[32005],dp[21][32005],nivmin[21][32005],niv[32005],timp,sortpoz[32005],grad[32005];
bool use[32005];
void esete(int nod)
{
use[nod]=1;
for(int i:muchii[nod])
if(!use[i])
esete(i);
st.push_back(nod);
}
void build(int nod)
{
use[nod]=1;
comp[nod]=nrcomp;
for(int i:muchii[nod])
if(!use[i])
build(i);
}
void dfs(int nod)
{
timp++;
in[nod]=timp;
use[nod]=1;
nivmin[0][nod]=niv[nod];
dp[0][nod]=par[nod];
for(int i=1;i<=20;i++)
dp[i][nod]=dp[i-1][dp[i-1][nod]];
for(int i:inv[nod])
nivmin[0][nod]=min(nivmin[0][nod],niv[i]);
for(int i:muchii[nod])
{
if(!use[i])
{
niv[i]=niv[nod]+1;
dfs(i);
}
nivmin[0][nod]=min(nivmin[0][nod],nivmin[0][i]);
}
out[nod]=timp;
}
int goup(int nod,int lg)
{
for(int i=20;i>=0;i--)
if((lg>>i)&1)
nod=dp[i][nod];
return nod;
}
bool isancestor(int a,int b)
{
return in[a]<=in[b]&&out[a]>=out[b];
}
int LCA(int a,int b)
{
if(niv[a]>niv[b])
swap(a,b);
if(isancestor(a,b))
return a;
for(int i=20;i>=0;i--)
if(dp[i][a]!=0&&!isancestor(dp[i][a],b))
a=dp[i][a];
return par[a];
}
int getrez(int a,int b)
{
int ans=0;
if(a==b)
return 0;
for(int i=20;i>=0;i--)
{
int x=nivmin[i][a];
if(x>niv[b])
{
ans+=(1<<i);
a=goup(a,niv[a]-x);
}
}
return ans+1;
}
bool bypoz(int a,int b)
{
return sortpoz[a]<sortpoz[b];
}
int main()
{
ios_base::sync_with_stdio(false);
fin.tie(0);
fin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b;
fin>>a>>b;
muchii[a].push_back(b);
g[i]={a,b};
}
for(int i=1;i<=n;i++)
if(!use[i])
esete(i);
reverse(st.begin(),st.end());
for(int i=1;i<=n;i++)
{
use[i]=0;
muchii[i].clear();
}
for(int i=1;i<=m;i++)
muchii[g[i].second].push_back(g[i].first);
for(int i:st)
if(!use[i])
{
nrcomp++;
build(i);
}
for(int i=1;i<=n;i++)
muchii[i].clear();
n=nrcomp;
for(int i=1;i<=m;i++)
{
int a=comp[g[i].first];
int b=comp[g[i].second];
if(a!=b)
{
muchii[a].push_back(b);
inv[b].push_back(a);
grad[b]++;
}
}
queue<int> coada;
for(int i=1;i<=n;i++)
if(grad[i]==0)
coada.push(i);
int cnt=0;
while(!coada.empty())
{
int nod=coada.front();
coada.pop();
cnt++;
sortpoz[nod]=cnt;
for(int i:muchii[nod])
{
grad[i]--;
if(grad[i]==0)
coada.push(i);
}
}
for(int i=1;i<=n;i++)
sort(muchii[i].begin(),muchii[i].end(),bypoz);
for(int i=1;i<=n;i++)
{
use[i]=0;
if(inv[i].empty())
{
assert(root==0);
root=i;
}
}
niv[root]=1;
dfs(root);
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++)
{
int nod=j;
int pozniv=nivmin[i-1][nod];
int poz=goup(nod,niv[nod]-pozniv);
nivmin[i][j]=nivmin[i-1][poz];
}
int q;
fin>>q;
while(q--)
{
int a,b;
fin>>a>>b;
a=comp[a];
b=comp[b];
int lca=LCA(a,b);
fout<<getrez(a,lca)<<'\n';
}
return 0;
}