公式
A - 噂の広がり / Spread of Rumors 解説 by admin
gpt-5.3-codex概要
記録を先頭から順に見て、「その時点で噂を知っている人だけが次の人に伝えられる」という条件をそのままシミュレーションする問題です。
各生徒が噂を知っているかどうかを管理すれば、最後の人数を効率よく求められます。
考察
この問題の本質は 「記録の順番が重要」 という点です。
たとえば、記録が
- \((1,2)\)
- \((0,1)\)
だった場合、1番目の時点では生徒1はまだ知らないので生徒2には伝わりません。
その後2番目で生徒1が知っても、もう1番目の記録には戻れないため、生徒2は最後まで知らないままです。
つまり、グラフを作って単純に「0から到達できる頂点数」を数えるだけでは不正解(WA)になります。
時系列どおりに1回ずつ処理する必要があります。
素朴に「記録ごとに噂が広がるかを更新」する方針は正しく、さらに各記録でやることは定数時間です:
- \(a_i\) が知っているなら \(b_i\) を知っている状態にする
- そうでなければ何もしない
これを \(M\) 件ぶん繰り返せばよいです。
アルゴリズム
- 長さ \(N\) の真偽値配列
knowを用意し、全員Falseで初期化。 - 最初に知っているのは生徒0だけなので
know[0] = True。 - 現在知っている人数
cnt = 1とする。 - 各記録 \((a,b)\) を順に処理:
know[a]がTrueかつknow[b]がFalseなら、know[b] = Truecnt += 1
- それ以外は何もしない。
- 最後に
cntを出力。
この方法なら、記録順の条件を厳密に満たしつつ高速に解けます。
計算量
- 時間計算量: \(O(M)\)
(各記録を1回ずつ、定数時間で処理) - 空間計算量: \(O(N)\)
(噂を知っているかどうかの配列)
実装のポイント
know[b]がすでにTrueのときにcntを増やさないこと(重複加算防止)。入力サイズが大きいので
sys.stdin.readlineを使うと安全です。\(M=0\) の場合でも、生徒0は必ず知っているため答えは1です(この実装は自然に対応済み)。
ソースコード
import sys
def main():
input = sys.stdin.readline
N, M = map(int, input().split())
know = [False] * N
know[0] = True
cnt = 1
for _ in range(M):
a, b = map(int, input().split())
if know[a] and not know[b]:
know[b] = True
cnt += 1
print(cnt)
if __name__ == "__main__":
main()
この解説は gpt-5.3-codex によって生成されました。
投稿日時:
最終更新: