Cod sursa(job #2093432)

Utilizator Stefan_RaduStefan Radu Stefan_Radu Data 23 decembrie 2017 17:50:02
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.96 kb
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

ifstream cin("lca.in");
ofstream cout("lca.out");

class Hpd {
public:

  Hpd(int n, int m) { 
    this -> n = n;
    this -> m = m;
    _chain.resize(n + 1);
    _level.resize(n + 1);
    _chain_lvl.resize(n + 1);
    _tata.resize(n + 1);
    _chain_of.resize(n + 1);
    _weight.resize(n + 1);
    _gr.resize(n + 1);
    max_chain = 0;
    max_chain_lvl = 0;

    for (int i = 2; i <= n; i ++) {
      cin >> _tata[i];
      _gr[_tata[i]].push_back(i);
    }

    _Init(1, 1);
    _Set_lvl(1, 1);

    lim = log2(max_chain_lvl);
    _dp.resize(lim + 1);
    for (auto &x : _dp) {
      x.resize(n + 1);
    }

    for (int i = 1; i <= n; i ++) {
      _dp[0][i] = _tata[_chain[_chain_of[i]].back()];
    }

    for (int i = 1; i <= lim; i ++) {
      for (int j = 1; j <= n; j ++) {
        _dp[i][j] = _dp[i - 1][_dp[i - 1][j]];
      }
    }
  }

  void Solve() {

    int x, y;
    for (int i = 1; i <= m; i ++) {
      
      cin >> x >> y;
      if (_chain_lvl[x] > _chain_lvl[y]) {
        swap(x, y);
      }

      int dif = _chain_lvl[y] - _chain_lvl[x];
      int bit = 0;
      while (dif) {
        if (dif & 1) {
          y = _dp[bit][y];
        }

        dif >>= 1;
        bit += 1;
      }
      
      for (int i = lim; i >= 0; i --) {
        if (_chain_of[_dp[i][x]] != _chain_of[_dp[i][y]]) {
          x = _dp[i][x];
          y = _dp[i][y];
        }
      }

      if (_chain_of[x] != _chain_of[y]) {
        x = _dp[0][x];
        y = _dp[0][y];
      }

      if (_level[x] >= _level[y]) {
        cout << y << '\n';
      }
      else {
        cout << x << '\n';
      }
    }
  }

private:

  int n, m, max_chain, lim, max_chain_lvl;
  vector < int > _level, _chain_of, _weight, _tata, _chain_lvl;
  vector < vector < int > > _chain, _gr, _dp;
  
  void _Init(int cur_node, int cur_level) {
    
    _level[cur_node] = cur_level;
    if (_gr[cur_node].size() == 0) {
      _chain[++ max_chain].push_back(cur_node);
      _chain_of[cur_node] = max_chain;
      _weight[max_chain] = 1;
      return;
    }
  
    int best = -1, max_w = -1;
    for (auto x : _gr[cur_node]) {
      _Init(x, cur_level + 1);
      if (_weight[_chain_of[x]] > max_w) {
        best = x;
        max_w = _weight[_chain_of[x]];
      }
    }

    _chain[_chain_of[best]].push_back(cur_node);
    _chain_of[cur_node] = _chain_of[best];
    _weight[_chain_of[best]] += 1;
    for (auto x : _gr[cur_node]) {
      if (x == best) {
        continue;
      }
      _weight[_chain_of[best]] += _weight[_chain_of[x]];
    }
  }

  void _Set_lvl(int cur_node, int cur_level) {
    
    _chain_lvl[cur_node] = cur_level;
    max_chain_lvl = max(max_chain_lvl, cur_level);
    for (auto x : _gr[cur_node]) {
      if (_chain_of[x] != _chain_of[cur_node]) {
        _Set_lvl(x, cur_level + 1);
      }
      else {
        _Set_lvl(x, cur_level);
      }
    }
  }
};

int main() {
  
  int n, m;
  cin >> n >> m;
  Hpd *H = new Hpd(n, m);
  //H -> Solve();
}