CP-templates

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub Misuki743/CP-templates

:heavy_check_mark: tree/weighted_tree_diameter.cpp

Verified with

Code

template<integral T>
auto weighted_tree_diameter(vc<tuple<int, int, T>> &e) {
  const int n = ssize(e) + 1;
  constexpr T NINF = numeric_limits<T>::min();

  vi adj0(n), d0(n);
  vc<T> w0(n);
  for(auto [u, v, w] : e) {
    adj0[u] ^= v, adj0[v] ^= u;
    d0[u]++, d0[v]++;
    w0[u] ^= w, w0[v] ^= w;
  }

  auto xor_link_traversal = [&](int s) {
    vi adj = adj0, d = d0, p(n, -1), ord;
    vc<T> w = w0;

    d[s] = 0;
    ord.reserve(n);
    for(int i = 0; i < n; i++) {
      int v = i;
      while(d[v] == 1) {
        ord.emplace_back(v);
        p[v] = adj[v], d[v] = 0, d[p[v]]--;
        adj[p[v]] ^= v, w[p[v]] ^= w[v];
        v = p[v];
      }
    }

    auto far = pair(NINF, -1);
    for(int v : ord | views::reverse) {
      w[v] += w[p[v]];
      if (w[v] > far.first)
        far = pair(w[v], v);
    }

    return pair(far, p);
  };

  int u = xor_link_traversal(0).first.second;
  auto [far, p] = xor_link_traversal(u);
  auto [diameter, v] = far;
  vi path = {v};
  while(path.back() != u)
    path.emplace_back(p[path.back()]);

  return pair(diameter, path);
}
#line 1 "tree/weighted_tree_diameter.cpp"
template<integral T>
auto weighted_tree_diameter(vc<tuple<int, int, T>> &e) {
  const int n = ssize(e) + 1;
  constexpr T NINF = numeric_limits<T>::min();

  vi adj0(n), d0(n);
  vc<T> w0(n);
  for(auto [u, v, w] : e) {
    adj0[u] ^= v, adj0[v] ^= u;
    d0[u]++, d0[v]++;
    w0[u] ^= w, w0[v] ^= w;
  }

  auto xor_link_traversal = [&](int s) {
    vi adj = adj0, d = d0, p(n, -1), ord;
    vc<T> w = w0;

    d[s] = 0;
    ord.reserve(n);
    for(int i = 0; i < n; i++) {
      int v = i;
      while(d[v] == 1) {
        ord.emplace_back(v);
        p[v] = adj[v], d[v] = 0, d[p[v]]--;
        adj[p[v]] ^= v, w[p[v]] ^= w[v];
        v = p[v];
      }
    }

    auto far = pair(NINF, -1);
    for(int v : ord | views::reverse) {
      w[v] += w[p[v]];
      if (w[v] > far.first)
        far = pair(w[v], v);
    }

    return pair(far, p);
  };

  int u = xor_link_traversal(0).first.second;
  auto [far, p] = xor_link_traversal(u);
  auto [diameter, v] = far;
  vi path = {v};
  while(path.back() != u)
    path.emplace_back(p[path.back()]);

  return pair(diameter, path);
}
Back to top page