結果
問題 | No.382 シャイな人たち (2) |
ユーザー | nagiss |
提出日時 | 2020-10-12 04:09:07 |
言語 | Python3 (3.12.2 + numpy 1.26.4 + scipy 1.12.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 3,207 bytes |
コンパイル時間 | 168 ms |
コンパイル使用メモリ | 12,800 KB |
実行使用メモリ | 19,456 KB |
最終ジャッジ日時 | 2024-07-20 17:52:46 |
合計ジャッジ時間 | 19,308 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | TLE | - |
testcase_01 | -- | - |
testcase_02 | -- | - |
testcase_03 | -- | - |
testcase_04 | -- | - |
testcase_05 | -- | - |
testcase_06 | -- | - |
testcase_07 | -- | - |
testcase_08 | -- | - |
testcase_09 | -- | - |
testcase_10 | -- | - |
testcase_11 | -- | - |
testcase_12 | -- | - |
testcase_13 | -- | - |
testcase_14 | -- | - |
testcase_15 | -- | - |
testcase_16 | -- | - |
testcase_17 | -- | - |
testcase_18 | -- | - |
testcase_19 | -- | - |
testcase_20 | -- | - |
ソースコード
class MaxClique: # 最大クリーク # Bron–Kerbosch algorithm (O(1.4422^|V|)) の枝刈りをしたもの # 参考: https://atcoder.jp/contests/code-thanks-festival-2017-open/submissions/2691674 # 検証1: https://atcoder.jp/contests/code-thanks-festival-2017-open/submissions/7620028 # 検証2: https://judge.yosupo.jp/submission/12486 def __init__(self, n): self.n = n self.E = [0] * n self.stk = [0] * n # 最大クリークが入るスタック def __repr__(self): return "\n".join("{:0{}b}".format(e, self.n) for e in self.E) def add_edge(self, v, u): # assert v != u self.E[v] |= 1 << u self.E[u] |= 1 << v def invert(self): # 補グラフにする n, E = self.n, self.E mask = (1<<n) - 1 # 正の数にしないと popcount がバグる for i in range(n): E[i] = ~E[i] & (mask ^ 1<<i) # 自己ループがあるとバグる def solve(self): n, E = self.n, self.E deg = [bin(v).count("1") for v in E] self.index = index = sorted(range(n), key=lambda x: deg[x], reverse=True) # 頂点番号を次数の降順にソート self.E_sorted = E_sorted = [] # E を 次数の降順に並び替えたもの for v in index: E_sorted_ = 0 E_v = E[v] for i, u in enumerate(index): if E_v >> u & 1: E_sorted_ |= 1 << i E_sorted.append(E_sorted_) cand = (1 << n) - 1 # 候補の集合 self.cans = 1 # 最大クリークを構成する集合 # 復元するときはこれを使う self.ans = 1 self._dfs(0, cand) return self.ans def _dfs(self, elem_num, candi): if self.ans < elem_num: self.ans = elem_num cans_ = 0 index = self.index for s in self.stk[:elem_num]: cans_ |= 1 << index[s] self.cans = cans_ potential = elem_num + bin(candi).count("1") if potential <= self.ans: return E_sorted = self.E_sorted pivot = (candi & -candi).bit_length() - 1 # 候補から頂点をひとつ取り出す smaller_candi = candi & ~E_sorted[pivot] # pivot と直接結ばれていない頂点の集合(自己ループの無いグラフなので pivot を含む) while smaller_candi and potential > self.ans: next = smaller_candi & -smaller_candi candi ^= next smaller_candi ^= next potential -= 1 next = next.bit_length() - 1 if next == pivot or smaller_candi & E_sorted[next]: self.stk[elem_num] = next self._dfs(elem_num + 1, candi & E_sorted[next]) def main(): mod = 1000003 S = int(input()) S = S * 12345 % mod N = S % 120 + 2 S = S * 12345 % mod P = S mc = MaxClique(N) for i in range(N): for j in range(i+1, N): S = S * 12345 % mod if S < P: mc.add_edge(i, j) ans = mc.solve() + 1 print(ans) print(*[i+1 for i in range(N) if mc.cans>>i&1]) main()