C - 噂の拡散 / Spread of Rumors 解説 by admin
Claude 4.6 Opus (Thinking)Overview
This is a simulation problem where rumors gradually spread on a graph. Starting from \(K\) people who initially know the rumor, the rumor propagates to students who have “\(T\) or more friends who know the rumor,” and we need to find the total number of students who know the rumor in the end.
Analysis
Naive Approach and Its Issues
The simplest method is to “simulate one day at a time.” Each day, scan all students, and for each student who doesn’t know the rumor, count “how many of their friends know the rumor.” If the count is \(T\) or more, they newly learn the rumor. Repeat this process.
However, in the worst case, only one person may newly learn the rumor per day, and scanning all students and edges each day results in \(O(N \times (N + M))\), which causes TLE when \(N, M\) are \(2 \times 10^5\).
Key Insight: BFS-like Propagation
The spread of rumors has a structure similar to BFS (Breadth-First Search).
- For each student, maintain a counter
friend_counttracking “the number of friends who know the rumor” - At the exact moment the counter reaches \(T\), add the student to the queue
- Students dequeued learn the rumor, and their friends’ counters are updated
This way, each edge is processed at most once, enabling efficient simulation.
Concrete Example
For example, with \(N=5, T=2\), where students 1 and 2 initially know the rumor, and edges are \((1,3), (2,3), (3,4), (4,5)\):
- Initial state: Students 1, 2 know the rumor. Student 3’s
friend_countis 2 (friends 1 and 2 know it) → reaches the threshold \(T=2\), so it’s added to the queue - Student 3 learns the rumor: Student 4’s
friend_countincreases to 1 → still less than \(T=2\), so it’s not added to the queue - Termination: The queue becomes empty, and the students who ultimately know the rumor are students 1, 2, 3 — 3 people
Algorithm
- Build an adjacency list
adj - For the students who initially know the rumor, set
knows[c] = True - For each initial rumor-knowing student \(c\), increment
friend_count[nb]by 1 for each friend \(nb\). Iffriend_count[nb]becomes exactly \(T\), add \(nb\) to the queue - Dequeue a student
node, and if they don’t know the rumor yet andfriend_count[node] >= T:- Set
knows[node] = True - For each friend \(nb\) of
node, incrementfriend_count[nb]by 1, and if it reaches exactly \(T\), add it to the queue
- Set
- When the queue is empty, count and output the number of students where
knowsisTrue
Complexity
- Time complexity: \(O(N + M)\)
- Each student enters the queue at most once, and each edge is processed at most twice (once from each endpoint)
- Space complexity: \(O(N + M)\)
- Used for the adjacency list, counter array, queue, etc.
Implementation Notes
Timing of queue insertion: Add to the queue only at the exact moment
friend_countreaches \(T\). This prevents the same student from being added to the queue multiple times, maintaining efficiencyCheck when dequeuing: As a safeguard against duplicate queue entries, skip if
knows[node]is alreadyTrueCorrectness of simultaneous propagation: The problem states that “all new transmissions occur simultaneously,” but the BFS approach of adding to the queue when the counter reaches the threshold produces the same result. This is because whether a student learns the rumor depends on “the final number of friends who know the rumor,” which is independent of the propagation order
Source Code
import sys
from collections import deque
def main():
input_data = sys.stdin.buffer.read().split()
idx = 0
N = int(input_data[idx]); idx += 1
M = int(input_data[idx]); idx += 1
K = int(input_data[idx]); idx += 1
T = int(input_data[idx]); idx += 1
knows = [False] * (N + 1)
initial = []
for i in range(K):
c = int(input_data[idx]); idx += 1
initial.append(c)
knows[c] = True
adj = [[] for _ in range(N + 1)]
for i in range(M):
u = int(input_data[idx]); idx += 1
v = int(input_data[idx]); idx += 1
adj[u].append(v)
adj[v].append(u)
# count of friends who know the rumor
friend_count = [0] * (N + 1)
queue = deque()
# Initialize: for each initial knower, update their friends' counts
for c in initial:
for nb in adj[c]:
if not knows[nb]:
friend_count[nb] += 1
if friend_count[nb] == T:
queue.append(nb)
while queue:
node = queue.popleft()
if knows[node]:
continue
# Check if still meets threshold (it should since we only enqueue at threshold)
if friend_count[node] >= T:
knows[node] = True
for nb in adj[node]:
if not knows[nb]:
friend_count[nb] += 1
if friend_count[nb] == T:
queue.append(nb)
print(sum(knows[1:N+1]))
main()
This editorial was generated by claude4.6opus-thinking.