Cod sursa(job #2680145)

Utilizator ionutpop118Pop Ioan Cristian ionutpop118 Data 2 decembrie 2020 19:19:28
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.1 kb
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int NMAX = 10000;
const int LOGMAX = 15;

/// Depth-first search of the graph
void build_tree(int node, int current_level, vector <bool> &viz, vector < vector <int> > &graph, vector < vector <int> > &children, vector <int> &level) {
	viz[node] = 1;
    level[node] = current_level;
	for (unsigned int i = 0; i < graph[node].size(); ++i) {
		if (viz[graph[node][i]] == 0) {
			children[node].push_back(graph[node][i]);
			build_tree(graph[node][i], current_level + 1, viz, graph, children, level);
		}
	}
}

/// Transforms the graph into a tree
void get_tree(int root, int &n, vector < vector <int> > &graph, vector < vector <int> > &children, vector <int> &level) {
	vector <bool> viz(n + 1, 0);
	build_tree(root, 0, viz, graph, children, level);
}

/// Gets the k-th father of a node
int get_kth_father(int node, int k, int father[][NMAX + 5]) {
    for (int i = 0; (1 << i) <= k; ++i) {
        if ((k & (1 << i)) != 0) {
            node = father[i][node];
        }
    }
    return node;
}


vector <int> lca(vector< vector<int> > &graph, vector< pair <int, int> > &queries) {
    int n = graph.size() + 1;
    int q = queries.size() + 1;

    vector < vector <int> > children(n + 1); // List of children for each node
    vector <int> level(n + 1); // Level of a node in the Euler tour
    int nod, l;

    get_tree(1, n, graph, children, level);
    //return vector <int>();
    int father [LOGMAX + 5][NMAX + 5];
    memset(father, 0, sizeof(father));

    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < children[i].size(); ++j) {
            father[0][children[i][j]] = i;
        }
    }
    //return vector <int>();
    for (int i = 1; i <= LOGMAX; ++i)
        for (int j = 1; j <= n; ++j)
            father[i][j] = father[i - 1][father[i - 1][j]];

    vector <int> answer; // Query answers
    for (int i = 0; i < q; ++i) {
        int x = queries[i].first;
        int y = queries[i].second;
        if (level[x] > level[y]) {
            swap(x, y);
        }

        y = get_kth_father(y, level[y] - level[x], father);
        if (x == y) {
            answer.push_back(x);
            continue;
        }
        for (int j = LOGMAX - 1; j >= 0; --j) {

            if (father[j][x] != father[j][y]) {
                x = father[j][x];
                y = father[j][y];
            }
        }
        answer.push_back(father[0][x]);
    }
    return answer;
}

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

	int n, m, x, y;
	scanf("%d %d", &n, &m);
	vector< vector<int> > g(n + 1);
	vector< pair <int, int> > q;

	for (int i = 2; i <= n; ++i) {
		/*scanf("%d %d", &x, &y);
		g[x].push_back(y);
		g[y].push_back(x);*/
        scanf("%d", &x);
        g[x].push_back(i);
        g[i].push_back(x);
	}

	for (int i = 1; i <= m; ++i) {
		scanf("%d %d", &x, &y);
		q.push_back(make_pair(x, y));
	}

	vector <int> ans = lca(g, q);

    for (int i = 0; i < m; ++i) {
		printf("%d\n", ans[i]);
	}

	return 0;
}