Pagini recente » Cod sursa (job #3291551) | Cod sursa (job #2298208) | Cod sursa (job #3182854) | Cod sursa (job #3244390) | Cod sursa (job #3259625)
#include <bits/stdc++.h>
#include <unordered_set>
using namespace std;
const int MAX = 32e4;
int N, M;
vector<int>G[MAX + 3];
vector<int>Gt[MAX + 3];
unordered_set<int>Gctc[MAX + 3];
//traiesc cu speranta sincera ca toate astea intra in limita de memorie
vector<int>S;
int v[MAX + 3];
int v1[MAX + 3];
int cntctc;
int nr[MAX + 3];
int lvl[MAX + 3];
int up[MAX + 3][16];
int upp[MAX + 3][16];
int uparb[MAX + 3];
vector<pair<int, int>>tree[MAX + 3];
void dfs(int nod) {
v[nod] = 1;
for(auto i : G[nod]) {
if(!v[i]) {
dfs(i);
}
}
S.push_back(nod);
}
void dfs1(int nod) {
v[nod] = cntctc;
for(auto i : Gt[nod]) {
if(!v[i]) {
dfs1(i);
}
}
}
void dfs3(int nod, int parent = 0) {
lvl[nod] = lvl[parent] + 1;
uparb[nod] = lvl[parent];
for(auto i : tree[nod]) {
if(i.first != parent && i.second == 1) {
dfs3(i.first, nod);
uparb[nod] = min(uparb[nod], uparb[i.first]);
}
uparb[nod] = min(uparb[nod], lvl[i.first]);
}
}
void precalc(int nod, int parent = 0) {
up[nod][0] = parent;
upp[nod][0] = uparb[nod];
for(int i = 1; i <= 15; i++) {
up[nod][i] = up[up[nod][i - 1]][i - 1];
upp[nod][i] = upp[upp[nod][i - 1]][i - 1];
}
for(auto i : tree[nod]) {
if(i.first != parent && i.second == 1) {
precalc(i.first, nod);
}
}
}
int lca(int a, int b) {
int ans;
if(lvl[a] < lvl[b]) swap(a, b);
for(int i = 15; i >= 0; i--) {
if(lvl[up[a][i]] >= lvl[b]) a = up[a][i];
}
if(a == b) return a;
for(int i = 15; i >= 0; i--) {
if(up[a][i] != up[b][i]) {
a = up[a][i];
b = up[b][i];
}
}
return up[a][0];
}
int main() {
freopen("obiective.in", "r", stdin);
freopen("obiective.out", "w", stdout);
cin.tie(0); cout.tie(0);
ios_base::sync_with_stdio(false);
cin >> N >> M;
for(int i = 1; i <= M; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
Gt[v].push_back(u);
}
dfs(1);
reverse(S.begin(), S.end());
for(int i = 1; i <= N; i++) v[i] = 0;
for(int i = 0; i < N; i++) {
if(!v[S[i]]) {
cntctc++;
dfs1(S[i]);
}
}
for(int i = 1; i <= N; i++) {
for(auto j : G[i]) {
if(v[i] != v[j]) {
if(!Gctc[v[i]].count(v[j])) {
nr[v[j]]++;
}
Gctc[v[i]].insert(v[j]);
}
}
}
queue<int>q;
for(int i = 1; i <= cntctc; i++) {
if(nr[i] == 0) q.push(i);
}
while(!q.empty()) {
for(auto i : Gctc[q.front()]) {
nr[i]--;
if(nr[i] != 0) {
tree[i].push_back({q.front(), 0});
tree[q.front()].push_back({i, 0});
}
else {
tree[i].push_back({q.front(), 1});
tree[q.front()].push_back({i, 1});
q.push(i);
}
}
q.pop();
}
dfs3(1);
precalc(1);
int Q; cin >> Q;
while(Q--) {
int x, y; cin >> x >> y;
x = v[x]; y = v[y];
int lca1 = lca(x, y);
if(x == y || lca1 == x) {
cout << 0 << '\n';
continue;
}
int ans = 0;
for(int i = 15; i >= 0; i--) {
if(lvl[upp[x][i]] > lvl[lca1]) {
x = upp[x][i];
ans += (1 << i);
}
}
cout << ans + 1 << '\n';
}
}