Source: IMO-2020-P4
Category: Graph Theory

Problem: There is an integer $n > 1$. There are $n^2$ stations on a slope of a mountain, all at different altitudes. Each of two cable car companies, A and B, operates $k$ cable cars; each cable car provides a transfer from one of the stations to a higher one (with no intermediate stops). The $k$ cable cars of A have $k$ different starting points and kdifferent finishing points, and a cable car which starts higher also finishes higher. The same conditions hold for B. We say that two stations are linked by a company if one can start from the lower station and reach the higher one by using one or more cars of that company (no other movements between stations are allowed). Determine the smallest positive integer $k$ for which one can guarantee that there are\ntwo stations that are linked by both companies.

Answer: $k=n^2-n+1$

Reference solution:
Answer: $k = n^2 - n + 1$.

When $k = n^2-n$, a valid construction exists for $n=4$ which generalizes readily, demonstrating that this value is not sufficient. 

To see that $k = n^2-n+1$ is sufficient, view $A$ and $B$ as graphs whose vertices are the $n^2$ stations and whose edges are the cable cars. For each company, the condition that a cable car starting higher also finishes higher, with all starting points and finishing points being distinct, implies that the connected components of these graphs are paths (possibly with $0$ edges; the direction of these edges is irrelevant). 

Now, if $k = n^2-n+1$, it follows that $A$ and $B$ each have exactly $n^2 - k = n-1$ connected components. Since there are $n^2$ vertices in total and $n^2 = (n-1)(n+1) + 1$, by the Pigeonhole Principle, some component of $A$ has at least $n+1$ vertices. Because graph $B$ has only $n-1$ connected components, this component of $A$ must contain two vertices that belong to the same component of $B$. These two stations are therefore linked by both companies, as desired.

Grading guidelines:
(Partial) 1. Observed/modelled each company’s system as a directed graph on the stations, and correctly deduced from the “order-preserving” and “distinct start/endpoints” conditions that every vertex has indegree ≤1 and outdegree ≤1, hence each connected component is a path (or isolated vertex). 2. Derived the component count formula for one company: with k edges on n^2 vertices and components being paths, the number of connected components equals n^2−k. 3. Gave a correct extremal/pigeonhole step in one graph: from n^2=(n−1)(n+1)+1 and having only n−1 components, concluded that some component has at least n+1 vertices. (Almost) 1. Proved that k=n^2−n+1 is sufficient using the path-component structure and pigeonhole principle, but made a small counting slip (e.g. wrote “at most n−1 components” or miscomputed n^2−k) while the intended argument clearly yields the correct bound. 2. Presented the full sufficiency proof and the idea of a counterexample for k=n^2−n, but did not fully describe/verify the construction (or verified it only for one small n) while the generalization is immediate. 3. Solution is almost complete, but made minor mistakes which are not negligible.

Construction task:
For the specific case $n=33$, determine the maximum number of cable cars $k$ that each company can operate without creating any pair of stations linked by both companies. Provide an explicit construction for this maximum case.

Construction requirements:
- The $33^2 = 1089$ stations are numbered 1 to 1089 from lowest to highest altitude.
- Output a single Python expression that evaluates to a tuple of two sets: `(A_lines, B_lines)`.
- `A_lines` and `B_lines` are sets of tuples `(i, j)`, representing a cable car line from station `i` to station `j` for company A and B respectively.
- The configuration must satisfy all problem constraints for valid cable car operations (distinct start/end points, and a cable car starting higher finishes higher).
- The number of cars for each company must be exactly $k$ (the maximum possible counter-example size).
- Put ONLY the Python expression inside the construction block. Do not include any markdown formatting, explanations, or surrounding tags other than `<construct>...</construct>`.

Reference construction:
({(i, i + 1) for i in range(1, 1090) if i % 33 != 0}, {(i, i + 33) for i in range(1, 1057)})

Verifier code:
import sys

def verify():
    payload = sys.stdin.read().strip()
    if not payload:
        print("Empty input")
        return
    
    try:
        # Parse the payload directly as a Python expression.
        # eval is used because the reference construction uses comprehensions and range().
        data = eval(payload)
    except Exception as e:
        print(f"Failed to parse Python expression: {e}")
        return

    if type(data) is not tuple or len(data) != 2:
        print("Parsed object is not a tuple of exactly two elements")
        return
    
    A_lines, B_lines = data

    for name, lines in [("A_lines", A_lines), ("B_lines", B_lines)]:
        if type(lines) is not set:
            print(f"{name} is not a set")
            return
        for item in lines:
            if type(item) is not tuple or len(item) != 2:
                print(f"An item in {name} is not a tuple of exactly two elements")
                return
            u, v = item
            if type(u) is not int or type(v) is not int:
                print(f"An item in {name} contains non-integers")
                return
                
    if len(A_lines) != 1056:
        print(f"A_lines has {len(A_lines)} elements, expected 1056")
        return
    if len(B_lines) != 1056:
        print(f"B_lines has {len(B_lines)} elements, expected 1056")
        return

    for name, lines in [("A_lines", A_lines), ("B_lines", B_lines)]:
        u_set = set()
        v_set = set()
        sorted_lines = sorted(list(lines), key=lambda x: x[0])
        prev_v = -1
        
        for u, v in sorted_lines:
            if not (1 <= u <= 1089 and 1 <= v <= 1089):
                print(f"Station out of range in {name}: ({u}, {v})")
                return
            if u >= v:
                print(f"Invalid transfer in {name}: ({u}, {v}), must be u < v")
                return
            if u in u_set:
                print(f"Duplicate starting point {u} in {name}")
                return
            u_set.add(u)
            if v in v_set:
                print(f"Duplicate finishing point {v} in {name}")
                return
            v_set.add(v)
            if v <= prev_v:
                print(f"Monotonicity violated in {name}: sequence of v is not strictly increasing.")
                return
            prev_v = v

    def get_transitive_closure(lines):
        adj = {u: v for u, v in lines}
        closure = set()
        for start_node in adj:
            curr = start_node
            while curr in adj:
                nxt = adj[curr]
                closure.add((start_node, nxt))
                curr = nxt
        return closure

    A_closure = get_transitive_closure(A_lines)
    B_closure = get_transitive_closure(B_lines)
    
    intersection = A_closure.intersection(B_closure)
    if intersection:
        example = list(intersection)[0]
        print(f"Intersection is not empty. Found linked pairs in both companies, e.g., {example}.")
        return
        
    print("True")

if __name__ == "__main__":
    verify()