#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_1_B" #include <iostream> #include "Mylib/DataStructure/UnionFind/weighted_unionfind.cpp" #include "Mylib/IO/input_tuples.cpp" namespace hl = haar_lib; int main() { int n, q; std::cin >> n >> q; hl::weighted_unionfind<int> uf(n); for (auto [type, x, y] : hl::input_tuples<int, int, int>(q)) { if (type == 0) { int z; std::cin >> z; uf.merge(x, y, z); } else { if (uf.is_same(x, y)) { std::cout << uf.diff(x, y) << std::endl; } else { std::cout << "?" << std::endl; } } } return 0; }
#line 1 "test/aoj/DSL_1_B/main.test.cpp" #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_1_B" #include <iostream> #line 2 "Mylib/DataStructure/UnionFind/weighted_unionfind.cpp" #include <numeric> #include <vector> namespace haar_lib { template <typename T> class weighted_unionfind { public: using value_type = T; private: std::vector<int> parent_, depth_, size_; std::vector<T> weight_; int count_; public: weighted_unionfind() {} weighted_unionfind(int n) : parent_(n), depth_(n, 1), size_(n, 1), weight_(n, 0) { std::iota(parent_.begin(), parent_.end(), 0); } int root_of(int i) { if (parent_[i] == i) return i; else { const int p = root_of(parent_[i]); weight_[i] += weight_[parent_[i]]; return parent_[i] = p; } } T weight_of(int i) { root_of(i); return weight_[i]; } bool is_same(int i, int j) { return root_of(i) == root_of(j); } T diff(int i, int j) { return weight_of(i) - weight_of(j); } int merge(int i, int j, T w) { const int ri = root_of(i), rj = root_of(j); if (ri == rj) return ri; else { if (depth_[ri] < depth_[rj]) { parent_[ri] = rj; size_[rj] += size_[ri]; weight_[ri] = w - weight_[i] + weight_[j]; return rj; } else { parent_[rj] = ri; size_[ri] += size_[rj]; weight_[rj] = -w + weight_[i] - weight_[j]; if (depth_[ri] == depth_[rj]) ++depth_[ri]; return ri; } } } int size_of(int i) { return size_[root_of(i)]; } int count_groups() { return count_; } }; } // namespace haar_lib #line 2 "Mylib/IO/input_tuples.cpp" #include <initializer_list> #line 4 "Mylib/IO/input_tuples.cpp" #include <tuple> #include <utility> #line 6 "Mylib/IO/input_tuple.cpp" namespace haar_lib { template <typename T, size_t... I> static void input_tuple_helper(std::istream &s, T &val, std::index_sequence<I...>) { (void) std::initializer_list<int>{(void(s >> std::get<I>(val)), 0)...}; } template <typename T, typename U> std::istream &operator>>(std::istream &s, std::pair<T, U> &value) { s >> value.first >> value.second; return s; } template <typename... Args> std::istream &operator>>(std::istream &s, std::tuple<Args...> &value) { input_tuple_helper(s, value, std::make_index_sequence<sizeof...(Args)>()); return s; } } // namespace haar_lib #line 8 "Mylib/IO/input_tuples.cpp" namespace haar_lib { template <typename... Args> class InputTuples { struct iter { using value_type = std::tuple<Args...>; value_type value; bool fetched = false; int N, c = 0; value_type operator*() { if (not fetched) { std::cin >> value; } return value; } void operator++() { ++c; fetched = false; } bool operator!=(iter &) const { return c < N; } iter(int N) : N(N) {} }; int N; public: InputTuples(int N) : N(N) {} iter begin() const { return iter(N); } iter end() const { return iter(N); } }; template <typename... Args> auto input_tuples(int N) { return InputTuples<Args...>(N); } } // namespace haar_lib #line 6 "test/aoj/DSL_1_B/main.test.cpp" namespace hl = haar_lib; int main() { int n, q; std::cin >> n >> q; hl::weighted_unionfind<int> uf(n); for (auto [type, x, y] : hl::input_tuples<int, int, int>(q)) { if (type == 0) { int z; std::cin >> z; uf.merge(x, y, z); } else { if (uf.is_same(x, y)) { std::cout << uf.diff(x, y) << std::endl; } else { std::cout << "?" << std::endl; } } } return 0; }