結果
問題 | No.1865 Make Cycle |
ユーザー | kept1994 |
提出日時 | 2022-05-03 23:55:10 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 966 ms / 3,000 ms |
コード長 | 4,454 bytes |
コンパイル時間 | 202 ms |
コンパイル使用メモリ | 81,920 KB |
実行使用メモリ | 203,820 KB |
最終ジャッジ日時 | 2024-07-02 22:40:23 |
合計ジャッジ時間 | 14,289 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 567 ms
142,356 KB |
testcase_01 | AC | 385 ms
128,140 KB |
testcase_02 | AC | 590 ms
153,128 KB |
testcase_03 | AC | 308 ms
143,752 KB |
testcase_04 | AC | 475 ms
161,264 KB |
testcase_05 | AC | 578 ms
169,948 KB |
testcase_06 | AC | 510 ms
140,172 KB |
testcase_07 | AC | 538 ms
149,112 KB |
testcase_08 | AC | 695 ms
168,664 KB |
testcase_09 | AC | 565 ms
163,060 KB |
testcase_10 | AC | 598 ms
161,176 KB |
testcase_11 | AC | 585 ms
161,544 KB |
testcase_12 | AC | 472 ms
143,060 KB |
testcase_13 | AC | 524 ms
142,296 KB |
testcase_14 | AC | 441 ms
134,964 KB |
testcase_15 | AC | 700 ms
159,780 KB |
testcase_16 | AC | 702 ms
163,648 KB |
testcase_17 | AC | 523 ms
142,588 KB |
testcase_18 | AC | 593 ms
172,424 KB |
testcase_19 | AC | 966 ms
203,820 KB |
testcase_20 | AC | 47 ms
54,528 KB |
testcase_21 | AC | 48 ms
54,016 KB |
testcase_22 | AC | 47 ms
54,272 KB |
testcase_23 | AC | 47 ms
54,400 KB |
ソースコード
#!/usr/bin/env python3 import sys MOD = 998244353 from collections import deque import heapq class TopologicalTree: def __init__(self, N) -> None: self.topologicalOrder = [] self.N = N self.seen = [0] * N self.G = [[] for _ in range(N)] self.degree = [0] * N # 各ノードの入次数 return # 辺の追加 def addEdge(self, fromNode: int, toNode: int): self.G[fromNode].append(toNode) self.degree[toNode] += 1 def topologicalSort(self): deq = deque([node for node in range(self.N) if self.degree[node] == 0]) # 入次数0のものがスタート # 片っ端から入次数0のものを取り出していく。取り出すとそのノードから遷移するノードの入次数をデクリメントする。 while deq: node = deq.popleft() self.topologicalOrder.append(node) for t in self.G[node]: self.degree[t] -= 1 if self.degree[t] == 0: deq.append(t) if [i for i in range(self.N) if self.degree[i]]: # 最終的な入次数が0じゃないものが残る場合循環がある。 return None return self.topologicalOrder def topologicalSort_heapq(self): """ 辞書順最小のトポロジカル順序を必要とする場合。 queueではなくheapqを使うため、入次数0のものの中で辞書順最小のnodeが選ばれる。 """ hq = [node for node in range(self.N) if self.degree[node] == 0] # 入次数0のものがスタート heapq.heapify(hq) # 片っ端から入次数0のものを取り出していく。取り出すとそのノードから遷移するノードの入次数をデクリメントする。 while hq: node = heapq.heappop(hq) self.topologicalOrder.append(node) for t in self.G[node]: self.degree[t] -= 1 if self.degree[t] == 0: heapq.heappush(hq, t) if [i for i in range(self.N) if self.degree[i]]: # 最終的な入次数が0じゃないものが残る場合循環がある。 return None return self.topologicalOrder def isUniqueOrder(self): """ トポロジカル順序が一意に定まるかを返す。 一般に、トポロジカルソート順 v1,v2,…,vN において、連続する2要素 vi,vi+1 の間に辺がないとき、その2要素を入れ替えることができることを利用。 https://drken1215.hatenablog.com/entry/2021/01/02/164800 """ for node in range(self.N - 1): if not self.topologicalOrder[node + 1] in self.G[self.topologicalOrder[node]]: return True else: return False # トポロジカルソートした結果の数列が何通りあるか -> bitDP # https://ferin-tech.hatenablog.com/entry/2017/01/24/184750 def main(): N, Q = list(map(int, input().split())) queries = [] for _ in range(Q): queries.append(list(map(int, input().split()))) # True ------ ok | ng ---- False def is_ok(k: int): tr = TopologicalTree(N) for a, b in queries[:k]: tr.addEdge(a - 1, b - 1) l = tr.topologicalSort() # print("#", l) return l != None # 条件式 def binSearch(ok: int, ng: int): # print(ok, ng) # はじめの2値の状態 while abs(ok - ng) > 1: # 終了条件(差が1となり境界を見つけた時) mid = (ok + ng) // 2 # print("target > ", mid) result = is_ok(mid) # print(result) if result: ok = mid # midが条件を満たすならmidまではokなのでokの方を真ん中まで持っていく else: ng = mid # midが条件を満たさないならmidまではngなのでngの方を真ん中まで持っていく # print(ok, ng) # 半分に切り分ける毎の2値の状態 return ng # 関数呼び出し時の引数のngは絶対評価されないのでngに書く値が答えになりうるならその数マイナス1を指定する。 ans = binSearch(0, Q) print(ans if ans < Q else -1) return if __name__ == '__main__': main()