A - プレゼントが届かない人 / People Who Don't Receive Presents Editorial by admin
GPT 5.2 High概要
各生徒が「誰にプレゼントを渡したか」が与えられるので、誰からも渡されていない(=1つも受け取っていない)生徒の人数を数える問題です。
考察
各生徒はちょうど1人にプレゼントを渡します。つまり「生徒 \(i \rightarrow T_i\)」という有向辺を \(N\) 本持つグラフだと考えられます。
このとき、生徒 \(x\) がプレゼントを受け取った回数は、辺が \(x\) に向かって入ってくる本数(入次数)と一致します。
したがって「プレゼントを1つも受け取れない生徒」とは、入次数が \(0\) の頂点です。
素朴な方法が遅い理由
例えば「生徒 \(i\) が誰かから受け取っているか」を、生徒全員の \(T_j\) を調べて確認すると、 - 各 \(i\) について \(j=1..N\) を走査 → \(O(N)\) - これを \(N\) 人分 → 合計 \(O(N^2)\)
\(N \le 2 \times 10^5\) なので \(O(N^2)\) は到底間に合いません。
解決策
全員の \(T_i\) を1回だけ見て、受け取る側のカウント(入次数)を配列で増やしていけば、合計 \(O(N)\) で求められます。
具体例
\(N=4,\ T=[2,2,4,2]\) のとき、 - 2 は 1,4,? から計3回(実際は 1,2,4 から)受け取る → 入次数 3 - 4 は 3 から1回受け取る → 入次数 1 - 1 と 3 は誰からも受け取らない → 入次数 0
よって答えは 2 人です。
アルゴリズム
- 長さ \(N+1\) の配列
indegを用意し、すべて 0 で初期化する(1-indexed)。 - 各 \(i=1..N\) について、
indeg[T_i] += 1として入次数を数える。 indeg[i] == 0を満たす \(i=1..N\) の個数を数えて出力する。
計算量
- 時間計算量: \(O(N)\)(\(T_i\) を1回数え、最後に1回数えるだけ)
- 空間計算量: \(O(N)\)(入次数配列)
実装のポイント
添字を分かりやすくするため、
indegはN+1要素にして生徒番号をそのまま index に使う(1-indexed)。入力サイズが大きいので、Python では
sys.stdin.buffer.read()を使うと安全に高速化できます。ソースコード
import sys
def main():
data = list(map(int, sys.stdin.buffer.read().split()))
N = data[0]
T = data[1:]
indeg = [0] * (N + 1)
for t in T:
indeg[t] += 1
ans = 0
for i in range(1, N + 1):
if indeg[i] == 0:
ans += 1
print(ans)
if __name__ == "__main__":
main()
この解説は gpt-5.2-high によって生成されました。