This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub tkmst201/Library
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1330" #include "DataStructure/PotentializedUnionFind.hpp" #include <cstdio> int main() { int N, M; while(scanf("%d %d", &N, &M), N || M) { PotentializedUnionFind<int> puf(N, 0, [](int a, int b){ return a + b; }); for (int i = 0; i < M; ++i) { char c; int a, b; scanf(" %c %d %d", &c, &a, &b); --a; --b; if (c == '!') { int w; scanf("%d", &w); if (!puf.issame(a, b)) puf.merge(a, b, w); } else { if (puf.issame(a, b)) printf("%d\n", puf.diff(a, b)); else puts("UNKNOWN"); } } } }
#line 1 "Test/PotentializedUnionFind.test.cpp" #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1330" #line 1 "DataStructure/PotentializedUnionFind.hpp" #include <cassert> #include <vector> #include <functional> #include <utility> /** * @brief https://tkmst201.github.io/Library/DataStructure/PotentializedUnionFind.hpp */ template<typename T> struct PotentializedUnionFind { using value_type = T; using const_reference = const value_type &; using size_type = std::size_t; using F = std::function<value_type (const_reference, const_reference)>; using G = std::function<value_type (const_reference)>; private: size_type n; value_type id_elem; F f; G g; std::vector<int> dat; std::vector<value_type> val; public: PotentializedUnionFind(size_type n, const_reference id_elem, const F & f, const G & g = [](const_reference x) { return -x; }) : n(n), id_elem(id_elem), f(f), g(g), dat(n, -1), val(n, id_elem) {} size_type size(size_type x) noexcept { assert(x < n); return -dat[find(x)]; } size_type find(size_type x) noexcept { assert(x < n); if (dat[x] < 0) return x; const size_type p = dat[x]; dat[x] = find(p); val[x] = f(val[x], val[p]); return dat[x]; } void merge(size_type x, size_type y, const_reference w) noexcept { assert(x < n); assert(y < n); size_type rx = find(x), ry = find(y); assert(rx != ry); value_type v = f(val[y], g(f(val[x], w))); if (dat[rx] < dat[ry]) { std::swap(rx, ry); v = g(v); } dat[ry] += dat[rx]; dat[rx] = ry; val[rx] = std::move(v); } value_type diff(size_type x, size_type y) noexcept { assert(x < n); assert(y < n); const size_type rx = find(x), ry = find(y); assert(rx == ry); return f(val[y], g(val[x])); } bool issame(size_type x, size_type y) noexcept { assert(x < n); assert(y < n); return find(x) == find(y); } }; #line 4 "Test/PotentializedUnionFind.test.cpp" #include <cstdio> int main() { int N, M; while(scanf("%d %d", &N, &M), N || M) { PotentializedUnionFind<int> puf(N, 0, [](int a, int b){ return a + b; }); for (int i = 0; i < M; ++i) { char c; int a, b; scanf(" %c %d %d", &c, &a, &b); --a; --b; if (c == '!') { int w; scanf("%d", &w); if (!puf.issame(a, b)) puf.merge(a, b, w); } else { if (puf.issame(a, b)) printf("%d\n", puf.diff(a, b)); else puts("UNKNOWN"); } } } }