Pagini recente » Cod sursa (job #1214842) | Cod sursa (job #120621) | Cod sursa (job #1535629) | Cod sursa (job #1602641) | Cod sursa (job #872528)
Cod sursa(job #872528)
#include<algorithm>
#include<fstream>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<cstring>
using namespace std;
ifstream in("obiective.in");
ofstream out("obiective.out");
const int N = 33000;
const int M = 66000;
int nr, n, m, t, a[M], b[M];
vector<int> v[N];
bool ver[N];
//CTC
int nrcomp, o[N], grad[N], rad;
map<int, int> conv;
set<pair<int, int> > temp;
vector<int> g[N], vt[N];
void df_ordine(int nod) {
ver[nod] = 1;
for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); ++it)
if(!ver[*it])
df_ordine(*it);
o[++nr] = nod;
}
void dfctc(int nod) {
ver[nod] = 1;
conv[nod] = nrcomp;
for(vector<int>::iterator it = vt[nod].begin(); it != vt[nod].end(); ++it) if(!ver[*it])
dfctc(*it);
}
void ctc() {
int i;
for(i = 1; i<=n; ++i) if(!ver[i])
df_ordine(i);
memset(ver, 0, sizeof(ver));
for(i = n; i; --i) if(!ver[o[i]]) {
++nrcomp;
dfctc(o[i]);
}
for(i = 1; i<=m; ++i) {
int ca = conv[a[i]], cb = conv[b[i]];
if(ca != cb && temp.find(pair<int, int>(ca, cb)) == temp.end()) {
g[ca].push_back(cb), grad[cb]++;
temp.insert(pair<int, int>(ca, cb));
}
}
}
//sortare topologica si sortarea muchiilor
int so[N], poz[N];
bool cmp(int nod1, int nod2) {
return poz[nod1] < poz[nod2];
}
void topsort() {
int i;
queue<int> q;
for(i = 1; i<=nrcomp; ++i) if(!grad[i]) {
q.push(i);
rad = i;
break;
}
nr = 0;
while(!q.empty()) {
int el = q.front();
q.pop();
so[++nr] = el;
poz[el] = nr;
for(vector<int>::iterator it = g[el].begin(); it != g[el].end(); ++it) {
grad[*it]--;
if(!grad[*it])
q.push(*it);
}
}
for(i = 1; i<=nrcomp; ++i) if(g[i].size())
sort(g[i].begin(), g[i].end(), cmp);
}
//liniarizarea arborelui
int cs[N], cd[N];
bool isAnc(int x, int y) {
return (cs[y] <= cs[x] && cd[y] >= cd[x]);
}
void dfsE(int nod) {
ver[nod] = 1;
cs[nod] = ++nr;
for(vector<int>::iterator it = g[nod].begin(); it != g[nod].end(); ++it) if(!ver[*it])
dfsE(*it);
cd[nod] = nr;
}
//calc nivmax
int niv[N], nivmax[19][N], el[19][N];
void dfsNiv(int nod) {
ver[nod] = 1;
for(vector<int>::iterator it = g[nod].begin(); it != g[nod].end(); ++it) {
if(!ver[*it]) {
niv[*it] = niv[nod] + 1;
nivmax[0][*it] = niv[nod];
el[0][*it] = nod;
dfsNiv(*it);
}
else {
if(nivmax[0][*it] > niv[nod])
el[0][*it] = nod;
nivmax[0][*it] = min(nivmax[0][*it], niv[nod]);
}
}
}
void calcStramosi() {
int i, j;
memset(ver, 0, sizeof(ver));
dfsNiv(rad);
for(i = 1; i < 19; ++i)
for(j = 1; j <= nrcomp; ++j) {
nivmax[i][j] = nivmax[i - 1][nivmax[i - 1][j]];
el[i][j] = el[i - 1][el[i - 1][j]];
}
}
int main() {
int i, n1, n2, j, nod, sol;
cs[0] = 0;
cd[0] = 1000000000;
in >> n >> m;
for(i = 1; i<=m; ++i) {
in >> a[i] >> b[i];
v[a[i]].push_back(b[i]);
vt[b[i]].push_back(a[i]);
}
ctc();
topsort();
memset(ver, 0, sizeof(ver)); nr = 0;
dfsE(rad);
calcStramosi();
in >> t;
for(i = 1; i<=t; ++i) {
in >> n1 >> n2;
n1 = conv[n1]; n2 = conv[n2];
if(n1 == n2 || isAnc(n2, n1)) {
out << 0 << "\n";
continue;
}
nod = n1;
sol = 0;
for(j = 18; j >= 0; --j)
if(!isAnc(n2, el[j][nod]))
nod = el[j][nod], sol += (1<<j);
if(isAnc(n2, el[0][nod]))
++sol;
out << sol << "\n";
}
return 0;
}