Pagini recente » Cod sursa (job #540329) | Monitorul de evaluare | Autentificare | Cod sursa (job #3301341) | Cod sursa (job #3301347)
#include <algorithm>
#include <iostream>
#include <fstream>
#include <climits>
#include <vector>
#include <stack>
#include <cmath>
#include <set>
// #include <bits/stdc++.h>
#define in fin
#define out fout
using namespace std;
ifstream fin("obiective.in");
ofstream fout("obiective.out");
vector<int> g[32000], gt[32000];
vector<int> st;
bool mr[32000];
vector< vector<int> > ctc;
int comp[32000];
void dfs1(int nod){
mr[nod] = 1;
for(const int &x : g[nod]){
if(mr[x]) continue;
dfs1(x);
}
st.push_back(nod);
}
void dfs2(int nod){
mr[nod] = 1;
comp[nod] = ctc.size() - 1;
ctc.back().push_back(nod);
for(const int &x : gt[nod]){
if(mr[x]) continue;
dfs2(x);
}
}
int d[32000]; // de cati oameni depinde
void build_copac(int nod){
set<int> pun;
for(const int &x : gt[nod]){
d[x]--;
if(d[x] == 0) pun.insert(x);
else g[x].push_back(nod);
}
for(const auto &x : pun){
g[nod].push_back(x);
build_copac(x);
}
}
int rmq[32000][16];
int niv[32000];
int start;
void dfs_nivel(int nod, int f){
// cerr << "nod = " << nod << '\n';
rmq[nod][0] = f;
for(const int &x : g[nod]){
if(niv[x] != 0 || x == 0) continue;
niv[x] = niv[nod] + 1;
dfs_nivel(x, nod);
}
}
void fa_rmq(){
for(int j = 1; (1 << j) < ctc.size(); j++){
for(int i = 0; i < ctc.size(); i++){
rmq[i][j] = rmq[ rmq[i][j - 1] ][j - 1];
}
}
}
int LCA(int a, int b){
if(niv[a] < niv[b]) swap(a, b);
for(int l = 15; l >= 0; l--){
if(niv[ rmq[a][l] ] >= niv[b]) a = rmq[a][l];
}
// cout << "ini a = " << a << " b = " << b << '\n';
if(a == b) return a;
for(int l = 15; l >= 0; l--){
if(rmq[a][l] != rmq[b][l]){ a = rmq[a][l]; b = rmq[b][l]; }
}
return rmq[a][0];
}
int rmq2[32000][16]; // asta e pt queriuri, celalalt era pt lca-uri
void calc_rmq_2(int nod, int f){
for(const int &x : g[nod]){
if(x != f && niv[rmq2[nod][0]] > niv[x]){ // e back-edge
rmq2[nod][0] = x;
}else if(niv[x] == niv[nod] + 1){
calc_rmq_2(x, nod);
if(niv[ rmq2[x][0] ] < niv[ rmq2[nod][0] ]) rmq2[nod][0] = rmq2[x][0];
}
}
}
void precalc_rmq2(){ // ca la rmq1 basically
for(int i = 0; i < ctc.size(); i++){
rmq2[i][0] = rmq[i][0];
}
calc_rmq_2(start, -1);
for(int j = 1; (1 << j) < ctc.size(); j++){
for(int i = 0; i < ctc.size(); i++){
rmq2[i][j] = rmq2[ rmq2[i][j - 1] ][j - 1];
}
}
}
int query(int a, int b){ // vreau sa ajung cu b peste lca dintre a si b
// cout << "Am nevoie sa fac intre " << a << " si " << b << '\n';
// cout << " -- > comp : " << comp[a] << " si " << comp[b] << '\n';
a = comp[a]; b = comp[b];
int lca = LCA(a, b);
// cout << " -- > lca = " << lca << '\n';
int sol = 0;
for(int l = 15; l >= 0; l--){
if(niv[ rmq2[a][l] ] > niv[lca]){
sol += (1 << l);
a = rmq2[a][l];
}
}
if(niv[a] > niv[lca]){
a = rmq[a][0]; sol++;
}
// cout << " -- > sol = " << sol << '\n';
// cout << " -- > a = " << a << " b = " << b << '\n';
return sol;
}
signed main(){
ios_base::sync_with_stdio(false);
in.tie(NULL);
int n, m; in >> n >> m;
for(int i = 0; i < m; i++){
int a, b; in >> a >> b;
a--; b--;
g[a].push_back(b);
gt[b].push_back(a);
}
for(int i = 0; i < n; i++){
if(!mr[i]) dfs1(i);
}
for(int i = 0; i < n; i++) mr[i] = 0;
for(int i = st.size() - 1; i >= 0; i--){
if(!mr[st[i]]){
ctc.push_back({});
dfs2(st[i]);
}
}
// cout << "St : ";
// for(int i = 0; i < st.size(); i++) cout << st[i] << " ";
// cout << '\n';
// cout << "ctc : \n";
// for(int i = 0; i < (int)ctc.size(); i++){
// for(const int &x : ctc[i]) cout << x << " ";
// cout << '\n';
// }
// acum condensam graful
set< pair<int, int> > ne; // new edges
for(int i = 0; i < n; i++){
for(const int &j : g[i]){
if(comp[i] != comp[j]){
ne.insert( make_pair(comp[i], comp[j]) );
// cout << "Trag muchie intre " << i << " si " << j << " ( " << comp[i] << " si " << comp[j] << " )\n";
}
}
g[i].clear();
gt[i].clear();
}
// cout << "new graf : \n";
for(const auto &x : ne){
// cout << x.first << " " << x.second << '\n';
gt[x.first].push_back(x.second);
d[x.second]++;
}
start = 0;
for(int i = 0; i < ctc.size(); i++){
if(d[i] == 0){ start = i; break; }
}
build_copac(start);
// cout << "copac : \n";
// for(int i = 0; i < n; i++){
// for(int j = 0; j < g[i].size(); j++){
// cout << "( " << i << " , " << g[i][j] << " )\n";
// }
// }
dfs_nivel(start, 0);
fa_rmq();
precalc_rmq2();
// cout << "start = " << start << '\n';
// cout << LCA(4, 3) << '\n';
int q; in >> q;
for(int i = 0; i < q; i++){
int a, b; in >> a >> b;
a--; b--;
out << query(a, b) << '\n';
}
return 0;
}
/*
5 5
1 2
1 3
3 4
1 4
4 5
0
8 9
8 1
8 2
1 4
8 4
4 5
2 3
3 7
3 6
2 7
3
1 7
4 8
4 1
*/