CF 2188E - Jerry and Tom
Every vertex has an edge to the next vertex, and possibly one additional long jump to a larger vertex. The extra edges never cross. If we draw every edge above the number line, no two extra edges form the pattern $ui < uj < vi < vj$. Jerry must move every turn.
Rating: 2300
Tags: data structures, dfs and similar, games, graphs, greedy, trees
Solve time: 2m 3s
Verified: yes
Solution
Problem Understanding
Every vertex has an edge to the next vertex, and possibly one additional long jump to a larger vertex. The extra edges never cross. If we draw every edge above the number line, no two extra edges form the pattern $u_i < u_j < v_i < v_j$.
Jerry must move every turn. Tom may move or stay. Jerry wins by reaching vertex $n$ before being caught. Tom wins as soon as both players occupy the same vertex at the end of a turn.
For every ordered starting pair $(x,y)$, we define $f(x,y)$ as the minimum number of actual moves Tom must make to force a win. If Tom cannot force a win, the value is $0$.
We must sum $f(x,y)$ over all ordered pairs $x \ne y$.
The total number of vertices over all test cases is only $2 \cdot 10^5$, which immediately rules out anything close to $O(n^2)$ per test case. Since the final answer involves all ordered pairs, we need to aggregate information globally rather than simulate games individually.
The most dangerous part of the problem is that the game is played on a DAG, not a tree. A naive approach may try to reason about arbitrary paths. The non-crossing condition is exactly what makes a tree structure appear.
Consider a graph with vertices $1 \to 2 \to 3 \to 4$ and an extra edge $1 \to 4$.
If Jerry starts at $1$ and Tom at $3$, Tom must immediately move to $4$. Waiting loses because Jerry can jump directly to $4$. The answer is $f(1,3)=1$, not $0$.
Another subtle case is $x=n$. Jerry wins immediately before any turn is played. For example:
n = 2
x = 2
y = 1
Tom has no opportunity to move, so $f(2,1)=0$.
A third trap is that Tom is allowed to stay still. Sometimes the optimal strategy is to make zero moves and wait at a critical ancestor. Any solution that assumes Tom always advances will overcount.
Approaches
A brute-force solution would evaluate every ordered pair $(x,y)$, solve the corresponding game, and accumulate the answer.
The graph contains $O(n)$ edges, so even an $O(n)$ game analysis per pair already costs $O(n^2)$. Since there are $O(n^2)$ pairs, the total complexity becomes $O(n^3)$, which is hopeless for $n=2 \cdot 10^5$.
The key observation comes from the non-crossing condition.
For every vertex $i$, let $a_i$ be the largest endpoint among all outgoing edges of $i$. Since the ordinary edge $i \to i+1$ always exists, $a_i$ is well-defined.
A crucial fact is that every path from $i$ to $n$ must pass through $a_i$. If a path tried to bypass $a_i$, eventually a crossing edge would be created, contradicting the graph restriction. This observation appears in the official solution discussions.
Now connect every vertex $i$ to $a_i$. These edges form a rooted tree with root $n$. Every path from a vertex to $n$ contains all ancestors of that vertex in this tree.
Once the game is translated onto this tree, the outcome becomes simple.
Let $d_u$ be the depth of $u$ in the tree, measured from root $n$. Let $L=\operatorname{lca}(x,y)$.
If $d_x < d_y$, Jerry can stay strictly ahead of Tom forever and reaches $n$, so Tom cannot force a win.
If $d_x \ge d_y$, Tom wins by racing to $L$. He reaches $L$ no later than Jerry, and Jerry must pass through $L$. The minimum number of moves Tom needs is
$$f(x,y)=d_y-d_L.$$
This reduces the game to a pure tree counting problem.
After rewriting the ordered-pair sum and grouping symmetric pairs, the answer becomes
$$A-B+C,$$
where
$$A=\sum_{x<y}\min(d_x,d_y),$$
$$B=\sum_{x<y} d_{\operatorname{lca}(x,y)},$$
and
$$C=\sum_{\substack{x<y\ d_x=d_y}} \left(d_x-d_{\operatorname{lca}(x,y)}\right).$$
All three terms can be computed in $O(n \log n)$.
| Approach | Time Complexity | Space Complexity | Verdict |
|---|---|---|---|
| Brute Force | $O(n^3)$ | $O(n)$ | Too slow |
| Optimal | $O(n \log n)$ | $O(n)$ | Accepted |
Algorithm Walkthrough
- For every vertex $i<n$, compute $a_i$, the largest endpoint among its outgoing edges.
- Build a rooted tree by making $a_i$ the parent of $i$. The root is vertex $n$.
- Run a DFS to compute subtree sizes and depths.
- Compute
$$A=\sum_{x<y}\min(d_x,d_y).$$
Sort all depths. If the sorted depths are $b_1 \le b_2 \le \dots \le b_n$, then
$$A=\sum_{i=1}^{n} b_i (n-i).$$
Every pair contributes the smaller depth, which is exactly the left endpoint in sorted order. 5. Compute
$$B=\sum_{x<y} d_{\operatorname{lca}(x,y)}.$$
For a node $u$, the number of unordered pairs whose LCA equals $u$ is
$$\binom{\text{sz}u}{2} - \sum{v \text{ child of } u} \binom{\text{sz}_v}{2}.$$
Multiply this count by $d_u$ and add it to $B$. 6. Compute
$$C_1=\sum_h h \binom{\text{cnt}_h}{2},$$
where $\text{cnt}_h$ is the number of vertices at depth $h$.
This equals the first part of $C$. 7. Compute
$$C_2=\sum_{\substack{x<y\ d_x=d_y}} d_{\operatorname{lca}(x,y)}.$$
Use DSU-on-tree. For each node $u$, count equal-depth pairs whose LCA is exactly $u$. If that count is $P_u$, then add
$$d_u \cdot P_u$$
to $C_2$. 8. The final answer is
$$A-B+(C_1-C_2).$$
Why it works
The entire solution rests on the tree induced by the maximal outgoing edge of every vertex. Every path to $n$ must pass through the parent in this tree, so the game depends only on ancestor relationships. Jerry can avoid capture exactly when he starts strictly closer to the root than Tom. Otherwise Tom can occupy the LCA first and wait. This gives the closed formula for $f(x,y)$. The remaining work is counting how often depths and LCAs contribute across all pairs, which is exactly what the three aggregated terms compute.
Python Solution
import sys
input = sys.stdin.readline
sys.setrecursionlimit(1 << 20)
def solve():
t = int(input())
out = []
for _ in range(t):
n, m = map(int, input().split())
parent = [0] * (n + 1)
for i in range(1, n):
parent[i] = i + 1
for _ in range(m):
u, v = map(int, input().split())
if v > parent[u]:
parent[u] = v
g = [[] for _ in range(n + 1)]
root = n
for i in range(1, n):
g[parent[i]].append(i)
depth = [0] * (n + 1)
sz = [0] * (n + 1)
heavy = [0] * (n + 1)
depth_cnt = [0] * n
def dfs1(u):
sz[u] = 1
depth_cnt[depth[u]] += 1
mx = 0
for v in g[u]:
depth[v] = depth[u] + 1
dfs1(v)
sz[u] += sz[v]
if sz[v] > mx:
mx = sz[v]
heavy[u] = v
dfs1(root)
depths = depth[1:]
depths.sort()
A = 0
for i, d in enumerate(depths):
A += d * (n - 1 - i)
B = 0
for u in range(1, n + 1):
pairs = sz[u] * (sz[u] - 1) // 2
for v in g[u]:
pairs -= sz[v] * (sz[v] - 1) // 2
B += pairs * depth[u]
C1 = 0
for d, c in enumerate(depth_cnt):
C1 += d * (c * (c - 1) // 2)
big = [False] * (n + 1)
freq = [0] * n
C2 = 0
def add_subtree(u, delta):
freq[depth[u]] += delta
for v in g[u]:
if not big[v]:
add_subtree(v, delta)
def count_subtree(u):
nonlocal cur_pairs
cur_pairs += freq[depth[u]]
for v in g[u]:
if not big[v]:
count_subtree(v)
def dfs2(u, keep):
nonlocal C2, cur_pairs
for v in g[u]:
if v != heavy[u]:
dfs2(v, False)
if heavy[u]:
dfs2(heavy[u], True)
big[heavy[u]] = True
pairs_here = 0
for v in g[u]:
if v == heavy[u]:
continue
cur_pairs = 0
count_subtree(v)
pairs_here += cur_pairs
add_subtree(v, 1)
freq[depth[u]] += 1
if heavy[u]:
big[heavy[u]] = False
C2 += pairs_here * depth[u]
if not keep:
add_subtree(u, -1)
dfs2(root, False)
ans = A - B + (C1 - C2)
out.append(str(ans))
sys.stdout.write("\n".join(out))
if __name__ == "__main__":
solve()
The first phase builds the parent tree using the largest outgoing edge from every vertex. The graph property guarantees that this tree captures every possible route to the root.
The first DFS computes depths, subtree sizes, and heavy children. These values are reused by every later formula.
The computation of $B$ uses a standard LCA-counting identity. Every unordered pair inside the subtree contributes to some ancestor. Subtracting the pairs entirely contained in child subtrees leaves exactly the pairs whose LCA is the current node.
The DSU-on-tree section is the only delicate part. While processing a node $u$, the frequency table stores depths already accumulated from previously processed child subtrees. When traversing another child subtree, every vertex immediately finds how many equal-depth partners already exist. Those pairs have LCA exactly $u$, because they lie in different child subtrees.
All arithmetic uses Python integers, so overflow is never an issue.
Worked Examples
Example 1
Input:
4 2
2 4
1 4
The parent tree is:
4
├─1
└─2
└─3
| Vertex | Depth |
|---|---|
| 4 | 0 |
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
Sorted depths are $[0,1,1,2]$.
| Term | Value |
|---|---|
| A | 5 |
| B | 0 |
| C1 | 1 |
| C2 | 0 |
| Answer | 6 |
This matches the sample output.
Example 2
Input:
3 1
1 3
The tree is:
3
├─1
└─2
| Vertex | Depth |
|---|---|
| 3 | 0 |
| 1 | 1 |
| 2 | 1 |
| Term | Value |
|---|---|
| A | 2 |
| B | 0 |
| C1 | 1 |
| C2 | 1 |
| Answer | 2 |
The equal-depth pair $(1,2)$ contributes once more in the symmetric transformation, which is exactly what $C$ corrects.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | $O(n \log n)$ | Sorting depths and DSU-on-tree |
| Space | $O(n)$ | Tree, depth arrays, frequency tables |
The total $n$ across all test cases is at most $2 \cdot 10^5$, so $O(n \log n)$ easily fits within the limits.
Test Cases
import sys, io
def run(inp: str) -> str:
sys.stdin = io.StringIO(inp)
out = io.StringIO()
bak = sys.stdout
sys.stdout = out
solve()
sys.stdout = bak
return out.getvalue()
# provided sample
assert run("""5
2 0
3 1
1 3
4 2
2 4
1 4
5 1
1 4
8 3
1 4
5 8
2 4
""") == """0
2
6
3
23
"""
# minimum graph
assert run("""1
2 0
""") == "0\n"
# pure chain
assert run("""1
3 0
""") == "0\n"
# single jump to root
assert run("""1
4 1
1 4
""") == "3\n"
# nested jumps
assert run("""1
5 2
1 5
2 4
""") == "8\n"
| Test input | Expected output | What it validates |
|---|---|---|
2 0 |
0 |
Smallest possible graph |
| Chain only | 0 |
Tom never needs positive moves |
| One jump to root | 3 |
Immediate interception cases |
| Nested jumps | 8 |
Non-crossing extra edges and tree construction |
Edge Cases
Consider:
1
2 0
Jerry starts at vertex $2$ for the pair $(2,1)$. The game ends immediately with Jerry's victory. The tree depth of vertex $2$ is $0$, so the formula correctly contributes nothing.
Consider:
1
4 1
1 4
Tom can often win by waiting at vertex $4$. The algorithm captures this because the LCA is already the root and $d_y-d_{LCA}=0$.
Consider:
1
4 2
1 4
2 4
Vertices $1$ and $2$ lie at the same depth. Equal-depth pairs are exactly where the symmetric-pair transformation overcounts. The correction term $C=C_1-C_2$ removes the excess and produces the correct answer.