tkmst201's Library

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

View the Project on GitHub tkmst201/Library

:heavy_check_mark: Test/PotentializedUnionFind.test.cpp

Depends on

Code

#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");
			}
		}
	}
}
Back to top page