結果
問題 | No.3009 Union-Find でつながろう! |
ユーザー |
![]() |
提出日時 | 2024-12-22 12:27:22 |
言語 | D (dmd 2.109.1) |
結果 |
AC
|
実行時間 | 649 ms / 2,000 ms |
コード長 | 4,615 bytes |
コンパイル時間 | 643 ms |
コンパイル使用メモリ | 84,076 KB |
実行使用メモリ | 6,528 KB |
最終ジャッジ日時 | 2025-01-17 20:50:45 |
合計ジャッジ時間 | 6,844 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 27 |
ソースコード
// n is known at the compile time// treat subsets of {0, 1, ..., n-1}struct BitSet(size_t n){static immutable bit_size = 8 * size_t.sizeof;static immutable data_size = (n % bit_size == 0 ? n/bit_size : n/bit_size+1);size_t[data_size] data;this (size_t[] elements ...) {foreach (elem; elements) {assert(elem < n);auto q = elem / bit_size;auto r = elem % bit_size;data[q] |= (1UL << r);}}BitSet opUnary(string op : "~")() {auto result = this;result.data[] = ~(result.data[]);return result;}// set operationsBitSet opBinary(string op)(BitSet rhs) {auto result = this;static if (op == "*" || op == "&") {result.data[] &= rhs.data[];}else if (op == "-") {result.data[] &= ~(rhs.data[]);}else if (op == "+" || op == "|") {result.data[] |= rhs.data[];}else assert(0);return result;}BitSet opBinary(string op)(size_t[] rhs ...) {return opBinary!op(new BitSet(n, rhs));}BitSet opOpAssign(string op)(BitSet rhs) {static if (op == "*" || op == "&") {this.data[] &= rhs.data[];}else if (op == "-") {this.data[] &= ~(rhs.data[]);}else if (op == "+" || op == "|") {this.data[] |= rhs.data[];}else assert(0);return this;}BitSet opOpAssign(string op)(size_t[] rhs ...) {return opOpAssign!op(BitSet!n(rhs));}bool opBinaryRight(string op : "in")(size_t lhs) {assert(lhs < n);auto q = lhs / bit_size;auto r = lhs % bit_size;return (data[q] & (1UL << r)) != 0;}bool opBinaryRight(string op : "in")(size_t[] lhs) {bool result = true;foreach (elem; lhs)result = result && (elem in this);return result;}size_t[] to_elements() {size_t[] result;foreach (q; 0 .. data_size) foreach (r; 0 .. bit_size) {auto i = q * bit_size + r;if (i >= n) break;if (data[q] & (1UL << r)) result ~= i;}return result;}size_t size() {size_t result;foreach (q; 0 .. data_size) foreach (r; 0 .. bit_size) {auto i = q * bit_size + r;if (i >= n) break;if (data[q] & (1UL << r)) ++result;}return result;}}// Union-tree of {0, 1, ..., num-1}class UnionFind {size_t num;private size_t[] parent;private size_t[] rank;private size_t[] size_;this (size_t num) {this.num = num;parent.length = num;foreach (n; 0 .. num) parent[n] = n;rank.length = num;size_.length = num;}size_t root(size_t n) {assert(n < num);if (parent[n] == n) return n;else return parent[n] = root(parent[n]); // recursively set the root}bool is_same(size_t n, size_t m) {assert(n < num && m < num);return root(n) == root(m);}// false if already unitedbool unite(size_t n, size_t m) {assert(n < num && m < num);auto rn = root(n), rm = root(m);if (rn == rm) return false;// swap if necessary to force rank[rm] <= rank[rn]if (rank[rn] < rank[rm]) {auto tmp = rm;rm = rn;rn = tmp;}parent[rm] = rn;if (rank[rn] == rank[rm]) ++rank[rn];size_[rn] += size_[rm] + 1;return true;}size_t size(size_t n) {return size_[root(n)]+1;}size_t size() {size_t result;foreach (i; 0 .. num)if (root(i) == i) result += 1;return result;}}// MAIN PARTimmutable M_max = 4096;alias Set = BitSet!M_max;// T.length = Mulong solve(ulong M, ulong N, Set[] Top) {auto tree = new UnionFind(N);foreach (i; 0 .. N) {// calculate the complement of the closure of {i}auto i_closure_complement = Set();foreach (U; Top) {if (i !in U) i_closure_complement |= U;}// for each j in the closure of {i}foreach (j; 0 .. N)if (j !in i_closure_complement)tree.unite(i, j);}return tree.size;}void main() {import std.stdio, std.conv, std.array;ulong M, N;{auto MN = readln().split();M = MN[0].to!ulong;N = MN[1].to!ulong;}// make the data of subsetsSet[] Top;foreach (m; 0 .. M) {Top ~= Set();auto bits = readln();foreach (i; 0 .. N) // remove the last \nif (bits[i] == '1') Top[m] += i;}solve(M, N, Top).writeln();}