Library

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

View the Project on GitHub noshi91/Library

:heavy_check_mark: test/potentialized_union_find.test.cpp

Depends on

Code

#define PROBLEM                                                                \
  "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_1_B&lang=ja"

#include "data_structure/potentialized_union_find.cpp"
#include "other/plus_group.cpp"

#include <iostream>

int main() {
#include "other/fast_ios.cpp"

  int n, q;
  std::cin >> n >> q;
  potentialized_union_find<plus_group<int>> puf(n);
  for (int i = 0; i != q; i += 1) {
    int c;
    std::cin >> c;
    switch (c) {
    case 0: {
      int x, y, z;
      std::cin >> x >> y >> z;
      if (!puf.same(x, y))
        puf.unite(x, y, z);
    } break;
    case 1: {
      int x, y;
      std::cin >> x >> y;
      if (puf.same(x, y))
        std::cout << puf.distance(x, y) << "\n";
      else
        std::cout << "?\n";
    } break;
    }
  }
}
#line 1 "test/potentialized_union_find.test.cpp"
#define PROBLEM                                                                \
  "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_1_B&lang=ja"

#line 2 "other/int_alias.cpp"

#include <cstddef>
#include <cstdint>

using i32 = std::int32_t;
using i64 = std::int64_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;
#line 2 "data_structure/potentialized_union_find.cpp"

#include <cassert>
#include <vector>
#include<utility>

template <class G> class potentialized_union_find {
  using T = typename G::value_type;
  class node_type {
  public:
    T value;
    usize parent;
    usize size;

    node_type(const T value, const usize parent, const usize size)
        : value(value), parent(parent), size(size) {}
  };

  std::vector<node_type> tree;

  void compress(const usize x) {
    const usize p = tree[x].parent;
    if (p == x)
      return;
    compress(p);
    tree[x].value = G::operation(tree[p].value, tree[x].value);
    tree[x].parent = tree[p].parent;
  }

public:
  potentialized_union_find() = default;

  explicit potentialized_union_find(const usize n)
      : tree(n, node_type(G::identity, 0, 1)) {
    for (usize i = 0; i != n; i += 1)
      tree[i].parent = i;
  }

  usize size() const { return tree.size(); }

  usize find(const usize x) {
    assert(x < size());

    compress(x);
    return tree[x].parent;
  }

  T potential(const usize x) {
    assert(x < size());

    compress(x);
    return tree[x].value;
  }

  bool same(const usize x, const usize y) {
    assert(x < size());

    compress(x);
    return find(x) == find(y);
  }

  T distance(const usize x, const usize y) {
    assert(x < size());
    assert(y < size());

    return G::operation(G::inverse(potential(x)), potential(y));
  }

  usize size(const usize x) {
    assert(x < size());

    return tree[find(x)].size;
  }

  void unite(usize x, usize y, T d) {
    assert(x < size());
    assert(y < size());
    assert(!same(x, y));

    if (size(x) < size(y)) {
      d = G::inverse(d);
      std::swap(x, y);
    }
    d = G::operation(G::operation(potential(x), d), G::inverse(potential(y)));
    x = find(x);
    y = find(y);
    tree[x].size += tree[y].size;
    tree[y].parent = x;
    tree[y].value = d;
  }
};

/**
 * @brief Potentialized Union Find
 */
#line 1 "other/plus_group.cpp"
template <class T> class plus_group {
public:
  using value_type = T;
  static constexpr T operation(const T &l, const T &r) noexcept {
    return l + r;
  }
  static constexpr T identity = 0;
  static constexpr T inverse(const T &x) noexcept { return -x; }
};
#line 6 "test/potentialized_union_find.test.cpp"

#include <iostream>

int main() {
#line 1 "other/fast_ios.cpp"
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#line 11 "test/potentialized_union_find.test.cpp"

  int n, q;
  std::cin >> n >> q;
  potentialized_union_find<plus_group<int>> puf(n);
  for (int i = 0; i != q; i += 1) {
    int c;
    std::cin >> c;
    switch (c) {
    case 0: {
      int x, y, z;
      std::cin >> x >> y >> z;
      if (!puf.same(x, y))
        puf.unite(x, y, z);
    } break;
    case 1: {
      int x, y;
      std::cin >> x >> y;
      if (puf.same(x, y))
        std::cout << puf.distance(x, y) << "\n";
      else
        std::cout << "?\n";
    } break;
    }
  }
}
Back to top page