結果
問題 | No.1420 国勢調査 (Easy) |
ユーザー |
![]() |
提出日時 | 2021-10-27 23:35:23 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 90 ms / 2,000 ms |
コード長 | 5,125 bytes |
コンパイル時間 | 1,806 ms |
コンパイル使用メモリ | 95,792 KB |
最終ジャッジ日時 | 2025-01-25 07:52:13 |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 30 |
ソースコード
#line 1 "unionfind/test/weighted_unionfind_F2.yuki1420.test.cpp"#define PROBLEM "https://yukicoder.me/problems/no/1420"#define ERROR 1 // Check only whether the answer is -1 or not#line 2 "number/nimber.hpp"#include <array>// Nimberstruct Nimber {using ull = unsigned long long;ull v;const static std::array<std::array<unsigned, 256>, 256> small_table;const static std::array<std::array<std::array<ull, 256>, 8>, 8> precalc;explicit operator bool() const { return v != 0; }Nimber(ull val = 0) : v(val) {}Nimber operator+(const Nimber &x) const { return Nimber(v ^ x.v); }Nimber operator-(const Nimber &x) const { return Nimber(v ^ x.v); }Nimber operator-() const { return *this; }Nimber &operator+=(const Nimber &x) { return *this = *this + x; }Nimber &operator-=(const Nimber &x) { return *this = *this + x; }template <class IStream> friend IStream &operator>>(IStream &is, Nimber &x) {ull v;return is >> v, x = Nimber(v), is;}template <class OStream> friend OStream &operator<<(OStream &os, const Nimber &x) {return os << x.v;}bool operator==(const Nimber &x) const { return v == x.v; }bool operator!=(const Nimber &x) const { return v != x.v; }bool operator<(const Nimber &x) const { return v < x.v; }static ull _rec(ull x, ull y) {if (x == 0 or y == 0) return 0;if (x < y) x ^= y, y ^= x, x ^= y; // Make x >= yif (y == 1) return x;for (int shift = 64 / 2;; shift >>= 1) {ull mask = (1ULL << shift) - 1;if (y >> shift) {ull v00 = _rec(x & mask, y & mask);ull v01 = _rec(x & mask, y >> shift);ull v10 = _rec(x >> shift, y & mask);ull v11 = _rec(x >> shift, y >> shift);return v00 ^ ((v01 ^ v10 ^ v11) << shift) ^ _rec(v11, 1ULL << (shift - 1));} else if (x >> shift) {return (_rec(x >> shift, y) << shift) ^ _rec(x & mask, y);}}}Nimber operator*(const Nimber &x) const {ull ret = 0;for (int d = 0; d < 8; ++d) {for (int e = 0; e < 8; ++e) {ret ^= precalc[d][e][small_table[(v >> (d * 8)) & 255][(x.v >> (e * 8)) & 255]];}}return Nimber(ret);}Nimber &operator*=(const Nimber &x) { return *this = *this * x; }};const std::array<std::array<unsigned, 256>, 256> Nimber::small_table = []() {std::array<std::array<unsigned, 256>, 256> ret;for (int i = 0; i < 256; ++i) {for (int j = 0; j < 256; ++j) ret[i][j] = _rec(i, j);}return ret;}();const std::array<std::array<std::array<unsigned long long, 256>, 8>, 8> Nimber::precalc = []() {std::array<std::array<std::array<unsigned long long, 256>, 8>, 8> ret;for (int d = 0; d < 8; ++d) {for (int e = 0; e < 8; ++e) {ull p = _rec(1ULL << (8 * d), 1ULL << (8 * e));for (int i = 0; i < 256; ++i) ret[d][e][i] = _rec(p, i);}}return ret;}();#line 2 "unionfind/weighted_unionfind.hpp"#include <numeric>#include <utility>#include <vector>// CUT begin// Weighted UnionFindtemplate <class S> struct WeightedUnionFind {std::vector<int> par, sz;std::vector<S> pot;WeightedUnionFind(int N = 0) : par(N), sz(N, 1), pot(N) { std::iota(par.begin(), par.end(), 0); }int find(int x) {if (par[x] != x) {int r = find(par[x]);pot[x] = pot[x] + pot[par[x]], par[x] = r;}return par[x];}bool unite(int s, int t, S rel_diff) {// Relate s and t by t = s + rel_diff// Return false iff contradiction happens.rel_diff = rel_diff + weight(s) + (-weight(t));if ((s = find(s)) == (t = find(t))) return rel_diff == 0;if (sz[s] < sz[t]) std::swap(s, t), rel_diff = -rel_diff;par[t] = s, sz[s] += sz[t], pot[t] = rel_diff;return true;}S weight(int x) { return find(x), pot[x]; }S diff(int s, int t) { return weight(t) + (-weight(s)); }int count(int x) { return sz[find(x)]; }bool same(int s, int t) { return find(s) == find(t); }};template <typename Int> struct F2vec {Int val;F2vec(Int x = 0) : val(x) {}F2vec operator+(const F2vec &y) const { return F2vec(y.val ^ val); }F2vec operator-() const { return *this; }bool operator==(const F2vec &x) const { return val == x.val; }template <class OStream> friend OStream &operator<<(OStream &os, const F2vec &x) { return os << x.val; }};#line 5 "unionfind/test/weighted_unionfind_F2.yuki1420.test.cpp"#include <iostream>using namespace std;int main() {cin.tie(nullptr), ios::sync_with_stdio(false);int N, M;cin >> N >> M;WeightedUnionFind<Nimber> uf(N);while (M--) {int a, b, y;cin >> a >> b >> y;a--, b--;if (!uf.unite(a, b, y)) {cout << "-1\n";return 0;}}for (int i = 0; i < N; i++) cout << uf.weight(i) << '\n';}