Cod sursa(job #2730424)

Utilizator gavra_bogdanBogdan Gavra gavra_bogdan Data 26 martie 2021 12:11:12
Problema Obiective Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.12 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>
#define Min(a, b) (((a)>(b))?(b):(a))

const int N = 32005;

std::vector<int>g[N], gt[N], l[N];
int st[N], c[N], k;
int f_app[N], rmq[20][N], mn[20][N], e;
bool viz[N];

void dfs1(int node) {
	for(int to:g[node]) if(!viz[to]) {
		viz[to] = true;
		dfs1(to);
	}
	st[++st[0]] = node;
}

void dfs2(int node) {
	for(int to:gt[node]) if(!viz[to]) {
		viz[to] = true;
		c[to] = k;
		dfs2(to);
	}
}

void euler_tour(int node = 1) {
	viz[node] = true;
	mn[0][++e] = node;
	f_app[node] = e;
	std::sort(l[node].begin(), l[node].end());
	for(int to:l[node]) if(!viz[to]) {
		euler_tour(to);
		mn[0][++e] = node;
		rmq[0][node] = Min(rmq[0][node], rmq[0][to]);
	}
}

int lca(int from, int to) {
	from = f_app[from], to = f_app[to];
	if(from>to) std::swap(from, to);
	int p2 = (int)log2(to-from);
	return Min(mn[p2][from], mn[p2][to-(1<<p2)+1]);
}

int solve(int from, int to) {
	int ans = 1;
	for(int i=20;i>=0;i--) if(rmq[i][from] > to) {
		from = rmq[i][from];
		ans+=(1<<i);
	}
	return ans;
}

int main() {
	std::ifstream fin("obiective.in");
	std::ofstream fout("obiective.out");
	int n, m, q, from, to;
	fin>>n>>m;
	for(int i=1;i<=m;i++) {
		fin>>from>>to;
		g[from].push_back(to);
		gt[to].push_back(from);
	}
	for(int i=1;i<=n;i++) if(!viz[i]) viz[i] = 1, dfs1(i);
	for(int i=1;i<=n;i++) viz[i] = false;
	for(int i=n;i>=1;i--) if(!viz[st[i]]) viz[st[i]] = 1, c[st[i]] = ++k, dfs2(st[i]);
	for(int i=1;i<=k;i++) rmq[0][i] = i;
	for(int i=1;i<=n;i++) 
		for(int to:g[i])
			if(c[to]!=c[i]) {
				l[c[from]].push_back(c[to]);
				rmq[0][c[to]] = Min(rmq[0][c[to]], c[i]);
			}
	for(int i=1;i<=k;i++) viz[i] = false;
	euler_tour();
	for(int j=1;(1<<j)<=k;j++)
		for(int i=1;i<=k;i++)
			rmq[j][i] = rmq[j-1][rmq[j-1][i]];
	for(int j=1;(1<<j)<=e;j++)
		for(int i=1;i+(1<<j)-1<=e;i++)
			mn[j][i] = Min(mn[j-1][i], mn[j-1][i+(1<<(j-1))]);
	fin>>q;
	while(q--) {
		fin>>from>>to;
		from = c[from], to = c[to];
		int Lca = lca(from, to);
		if(from==Lca or from==to) fout<<"0\n";
		else fout<<solve(from, Lca)<<"\n";
	}
}