Cod sursa(job #1787614)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 24 octombrie 2016 20:39:54
Problema Obiective Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.21 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <bitset>
#include <algorithm>
#define MAXN 32050
#define MAXLOG 19

using namespace std;

int n, m, nq, root;
bitset<MAXN> viz;
vector<int> graf[MAXN];
vector<int> trg[MAXN];
vector<int> dag[MAXN];
vector<int> postOrd;
vector<int> euler;

int gToDag[MAXN], loc[MAXN], depth[MAXN], pos[MAXN];
int rmq[MAXLOG][2*MAXN], lg[2*MAXN], low[MAXN], parent[MAXLOG][MAXN];
/// pos[i] => prima aparitie a nodului i din DAG in parcurgerea euler

void citire()
{
	scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
		int x, y;
		scanf("%d %d", &x, &y);
        graf[x].push_back(y);
        trg[y].push_back(x);
    }
}

void dfsRaw(int nod)
{
    viz[nod] = 1;
    for (int i = 0, t = graf[nod].size(); i < t; i++)
        if (!viz[graf[nod][i]])
			dfsRaw(graf[nod][i]);
    postOrd.push_back(nod);
}

void dfsTraw(int nod)
{
    viz[nod] = 1;
    gToDag[nod] = nq;
    for (int i = 0, t = trg[nod].size(); i < t; i++)
        if (!viz[trg[nod][i]])
			dfsTraw(trg[nod][i]);
}

void buildDAG()
{
	for (int i = 1; i <= n; i++)
		if (!viz[i])
			dfsRaw(i);
	viz = 0;
    for (int i = postOrd.size()-1; i >= 0; i--)
		if (!viz[postOrd[i]])
		{
			nq++;
            dfsTraw(postOrd[i]);
		}
	for (int i = 1; i <= n; i++)
		for (int j = 0, t = graf[i].size(); j < t; j++)
			if (gToDag[i] != gToDag[graf[i][j]])
				dag[gToDag[i]].push_back(gToDag[graf[i][j]]);
}

void agat()
{
	viz = 0;
	for (int i = 1; i <= nq; i++)
        for (int j = 0, t = dag[i].size(); j < t; j++)
			viz[dag[i][j]] = 1;
    for (int i = 1; i <= nq; i++)
		if (!viz[i]) {
			root = i;
			break;
		}
}

void dfs(int nod)
{
    viz[nod] = 1;
    for (int i = 0, t = dag[nod].size(); i < t; i++)
        if (!viz[dag[nod][i]])
			dfs(dag[nod][i]);
	postOrd.push_back(nod);
}

bool cmp(int e, int f)
{
    return loc[e] < loc[f];
}

void topologic()
{
	viz = 0;
    postOrd.clear();
    for (int i = 1; i <= nq; i++)
        if (!viz[i])
            dfs(i);
    for (int i = 0, t = postOrd.size()-1; t >= 0; t--, i++)
        loc[postOrd[t]] = i;
	for (int i = 1; i <= nq; i++) {
        sort(dag[i].begin(), dag[i].end(), cmp);
		vector<int> :: iterator last = unique(dag[i].begin(), dag[i].end());
		dag[i].erase(last, dag[i].end());
	}
}

void eulerS(int nod, int d)
{
    pos[nod] = euler.size();
    depth[nod] = d;
    euler.push_back(d);
    for (int i = 0, t = dag[nod].size(); i < t; i++)
	{
		int y = dag[nod][i];
        if (pos[y] == 0) {
            low[y] = d;
            parent[0][y] = nod;
			eulerS(y, d+1);
            euler.push_back(d);
        }
		if (d < low[y]) {
			low[y] = d;
            parent[0][nod] = nod;
		}
	}
	for (int i = 0, t = dag[nod].size(); i < t; i++) {
		int y = dag[nod][i];
        if (low[y] < low[nod])
		{
			low[nod] = low[y];
            parent[0][nod] = parent[0][y];
		}
	}
}

void prepareRmq()
{
    int sz = euler.size()-1;
    for (int i = 1; i <= sz; i++)
        rmq[0][i] = euler[i];
    for (int i = 1; i < MAXLOG; i++) {
        for (int j = 1; j+(1<<(i-1)) <= sz; j++) {
			rmq[i][j] = min(rmq[i-1][j], rmq[i-1][j+(1<<(i-1))]);
        }
    }
    for (int i = 2; i <= sz; i++)
		lg[i] = lg[i>>1]+1;
}

int LCA(int x, int y)
{
    int p1 = pos[x], p2 = pos[y], dist;
    if (p1 > p2) swap(p1, p2);
    dist = lg[p2-p1+1];
    return min(rmq[dist][p1], rmq[dist][p2+1-(1<<dist)]);
}

void buildStra(int x = root)
{
	parent[0][root] = -1;
	for (int i = 1; i < MAXLOG; i++)
        for (int j = 1; j <= nq; j++)
			parent[i][j] = parent[i-1][parent[i-1][j]];
}

int solve(int x, int y)
{
	x = gToDag[x], y = gToDag[y];
    int prag = LCA(x, y);
    if (depth[x] == prag) return 0;
    //if (low[x] <= prag) return 1;
    int rez = 0;
    for (int i = lg[depth[x]-prag]; i >=0 ; i--)
        if (parent[i][x] != -1 && depth[parent[i][x]] > prag) {
			rez += (1<<i);
            x = parent[i][x];
        }
	return rez+1;
}

int main()
{
    freopen("obiective.in", "r", stdin);
    freopen("obiective.out", "w", stdout);

    citire();
    buildDAG();
    agat();
    topologic();
    euler.push_back(-1);
    eulerS(root, 1);
    buildStra();
    prepareRmq();
    int t;
    scanf("%d", &t);
    while (t--) {
        int x, y;
        scanf("%d %d", &x, &y);
        printf("%d\n", solve(x, y));
    }

    return 0;
}