CP-templates

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

View the Project on GitHub Misuki743/CP-templates

:warning: ds_problem/zero_one_on_tree.cpp

Code

//#include<ds/monoidDSU>

struct min_monoid {
  using M = array<int, 2>;
  static M id() { return {INT_MAX, -1}; }
  static M op(const M& a, const M& b) {
    return min(a, b);
  }
};

template<class T>
T zero_one_on_tree(vector<vector<int>> g, vector<T> l, vector<T> a, int r = 0) {
  int n = ssize(g);

  vector<int> p(n, -1), d(n);
  {
    auto dfs = [&](int v, auto &&self) -> void {
      for(int x : g[v]) {
        if (x == p[v]) continue;
        d[x] = d[v] + 1, p[x] = v;
        self(x, self);
      }
    };
    dfs(r, dfs);
  }

  DSU<min_monoid::M, min_monoid::id, min_monoid::op> dsu([&]() {
    vector<min_monoid::M> init(n);
    for(int i = 0; i < n; i++)
      init[i] = {d[i], i};
    return init;
  }());

  using D = tuple<T, T, int>; //(l_v, a_v, v)
  auto cmp = [](D a, D b) {
    return get<1>(a) * get<0>(b) < get<0>(a) * get<1>(b);
  };
  priority_queue<D, vector<D>, decltype(cmp)> pq;
  for(int i = 0; i < n; i++)
    pq.push({l[i], a[i], i});

  T cost = 0, lsum = 0;
  vector<bool> vis(n, false);
  while(!pq.empty()) {
    auto [l_v, a_v, v] = pq.top(); pq.pop();
    if (l[v] != l_v or a[v] != a_v) continue;
    if (p[v] != -1 and !vis[dsu.get(p[v])[1]]) {
      dsu.merge(v, p[v]);
      int b = dsu.get(v)[1];
      cost += l[b] * a[v];
      l[b] += l[v], a[b] += a[v];
      pq.push({l[b], a[b], b});
    } else {
      vis[v] = true, cost += lsum * a[v], lsum += l[v];
    }
  }

  return cost;
}
#line 1 "ds_problem/zero_one_on_tree.cpp"
//#include<ds/monoidDSU>

struct min_monoid {
  using M = array<int, 2>;
  static M id() { return {INT_MAX, -1}; }
  static M op(const M& a, const M& b) {
    return min(a, b);
  }
};

template<class T>
T zero_one_on_tree(vector<vector<int>> g, vector<T> l, vector<T> a, int r = 0) {
  int n = ssize(g);

  vector<int> p(n, -1), d(n);
  {
    auto dfs = [&](int v, auto &&self) -> void {
      for(int x : g[v]) {
        if (x == p[v]) continue;
        d[x] = d[v] + 1, p[x] = v;
        self(x, self);
      }
    };
    dfs(r, dfs);
  }

  DSU<min_monoid::M, min_monoid::id, min_monoid::op> dsu([&]() {
    vector<min_monoid::M> init(n);
    for(int i = 0; i < n; i++)
      init[i] = {d[i], i};
    return init;
  }());

  using D = tuple<T, T, int>; //(l_v, a_v, v)
  auto cmp = [](D a, D b) {
    return get<1>(a) * get<0>(b) < get<0>(a) * get<1>(b);
  };
  priority_queue<D, vector<D>, decltype(cmp)> pq;
  for(int i = 0; i < n; i++)
    pq.push({l[i], a[i], i});

  T cost = 0, lsum = 0;
  vector<bool> vis(n, false);
  while(!pq.empty()) {
    auto [l_v, a_v, v] = pq.top(); pq.pop();
    if (l[v] != l_v or a[v] != a_v) continue;
    if (p[v] != -1 and !vis[dsu.get(p[v])[1]]) {
      dsu.merge(v, p[v]);
      int b = dsu.get(v)[1];
      cost += l[b] * a[v];
      l[b] += l[v], a[b] += a[v];
      pq.push({l[b], a[b], b});
    } else {
      vis[v] = true, cost += lsum * a[v], lsum += l[v];
    }
  }

  return cost;
}
Back to top page