H - 都市の巡回調査 / City Tour Survey 解説 by admin
GPT 5.2 HighOverview
This problem asks you to simulate traversing cities under the rule “prioritize the unvisited city with the highest importance,” and output the sequence of city numbers in the order they are surveyed. By fixing the importance ordering through preprocessing, the simulation can be executed efficiently.
Discussion
There are two types of “maximum” selections needed in this problem:
- During a tour: Among unvisited cities reachable by one edge from city \(u\), move to the city with the highest importance \(B\).
- Starting a tour: For the 2nd tour onward, start from the unvisited city with the highest importance \(B\).
Issues with a naive approach
- If we select the starting city each time by “searching all unvisited cities for the maximum \(B\),” this takes \(O(N)\) per tour start, and repeating this for each tour results in \(O(N^2)\) total, causing TLE (\(N \le 2\times 10^5\)).
- Finding “the maximum \(B\) among adjacent cities” during a tour also requires searching for the maximum each time. However, since each city becomes the “current city” only once (explained below), with some ingenuity this can be done in \(O(M)\) total.
Key observations
- The importance values \(B_i\) form a permutation (all distinct), so once we create a “list of cities in decreasing order of importance,” selecting the starting city simply requires scanning this list from the front to find the first unvisited city.
- Since tours “only move to unvisited cities,” each city is visited at most once (we never return to an already surveyed city).
Therefore, the process of finding “where to go next from \(u\)” only needs to happen once — when city \(u\) is visited.
With these two points, we can speed up both “selecting the starting city” and “selecting the best adjacent city” through preprocessing, making the overall solution fast enough.
Algorithm
Preprocessing
- Read the importance array \(B[i]\).
- Create a reverse lookup
inv[b]that maps importance value \(b\) to its city number (possible since \(B\) is a permutation). - Add each directed edge \(u \to v\) to the adjacency list
adj[u]. - For each city \(u\), sort
adj[u]in descending order of \(B[v]\).
This way, “the unvisited destination with the highest importance” can be found by simply taking the first unvisited entry from the front.
Additionally, create an array of cities sorted in descending order of importance:
[
\text{order_by_B} = [\text{city with importance }N, \text{city with importance }N-1, \dots]
]
using inv.
Tour
Implement tour(start) as follows:
- Start with
cur = start - Mark
curas surveyed and append it to the output sequence - Scan
adj[cur](sorted in descending importance) from the front, and find the first “unvisited” vertexnxt- If found, set
cur = nxtand continue - If not found, end the tour
- If found, set
Overall flow
- First, execute
tour(1)(as specified by the problem). - While there are still unsurveyed cities:
- Scan
order_by_Bfrom the front to find an unvisited city (simply advance the pointerpos) - Execute
tour(that city)with it as the starting city
- Scan
This produces the survey order exactly according to the rules.
Complexity
- Time complexity:
Sorting the adjacency lists takes \(\sum_u O(\deg(u)\log \deg(u)) \le O(M\log M)\).
The simulation part processes each city only once and traverses each edge at most once, totaling \(O(N+M)\).
Therefore, the overall complexity is \(O(M\log M + N + M)\) (the dominant term is typically \(O(M\log M)\)). - Space complexity: \(O(N+M)\) (adjacency lists, visit tracking, auxiliary arrays)
Implementation Notes
Sorting adjacency lists in descending order of \(B\) allows “the maximum unvisited adjacent city” to be found via a linear scan from the front.
Starting city selection uses the descending importance array
order_by_Band a pointerpos, avoiding a full search each time (just advanceposuntil an unvisited city is found).Since the input can be large, in Python using
sys.stdin.buffer.read()for fast input is effective.Source Code
import sys
def main():
data = list(map(int, sys.stdin.buffer.read().split()))
it = 0
N = data[it]; it += 1
M = data[it]; it += 1
B = [0] * (N + 1)
inv = [0] * (N + 1)
for i in range(1, N + 1):
b = data[it]; it += 1
B[i] = b
inv[b] = i
adj = [[] for _ in range(N + 1)]
for _ in range(M):
u = data[it]; v = data[it + 1]; it += 2
adj[u].append(v)
key = B.__getitem__
for u in range(1, N + 1):
if adj[u]:
adj[u].sort(key=key, reverse=True)
order_by_B = [inv[r] for r in range(N, 0, -1)]
pos = 0
visited = [False] * (N + 1)
out = []
def tour(start: int):
cur = start
while True:
visited[cur] = True
out.append(cur)
nxt = 0
for v in adj[cur]:
if not visited[v]:
nxt = v
break
if nxt == 0:
break
cur = nxt
tour(1)
while len(out) < N:
while pos < N and visited[order_by_B[pos]]:
pos += 1
tour(order_by_B[pos])
sys.stdout.write(" ".join(map(str, out)))
if __name__ == "__main__":
main()
This editorial was generated by gpt-5.2-high.
投稿日時:
最終更新: