CF 106239M - 敌人的敌人

We are given a collection of countries, where each country is a node in a graph and every direct enemy relationship is an edge.

CF 106239M - \u654c\u4eba\u7684\u654c\u4eba

Rating: -
Tags: -
Solve time: 51s
Verified: yes

Solution

Problem Understanding

We are given a collection of countries, where each country is a node in a graph and every direct enemy relationship is an edge. The important structural guarantee is that these relationships form a tree, so there are no cycles and the graph is connected with exactly n − 1 edges.

The notion of “friendship” is not given directly as an edge relation. Instead, it is derived from a rule: if a country x has an enemy y, and that enemy y has another enemy z, then z becomes a friend of x. In graph terms, this means that any node reachable from x by following exactly two edges corresponds to a friend of x. No further propagation happens beyond this rule, so friendship is strictly tied to paths of length exactly two.

The task is to compute, for every node, how many distinct nodes lie at distance exactly two from it, and then output any node that maximizes this value along with the maximum count.

The constraints imply that n can be up to 200,000 per test case with up to 10,000 test cases, but the sum of all n is bounded by 200,000. This immediately suggests that any algorithm must be linear over the total input size. A solution that is quadratic in n per test case would be far too slow, and even O(n log n) per test case would be risky if applied repeatedly.

A naive interpretation would suggest, for each node, running a BFS up to depth 2 and counting nodes at distance 2. While correct, this repeats a lot of work and risks O(n²) behavior in a star-shaped tree.

A few subtle cases are worth calling out. In a star-shaped tree where one center node connects to all others, a BFS from every leaf would repeatedly traverse the center and all other leaves, causing redundant work. Another edge case is a path graph: in a long chain, each BFS still walks a small portion, but cumulatively it still becomes quadratic.

The key observation is that distance-2 nodes can be counted purely from local degree information, without performing repeated traversals.

Approaches

A brute-force solution considers each node as a starting point and performs a BFS or DFS up to depth two. From a node x, it explores all neighbors y, and then all neighbors of y, collecting those at distance exactly two. This is correct because it directly follows the definition of friendship.

However, each BFS can touch up to O(n) nodes in a dense neighborhood, and doing this for every node leads to O(n²) total complexity in worst-case trees such as stars. The redundancy comes from repeatedly scanning the same adjacency lists.

The key structural insight is that any node z at distance exactly two from x must be connected through some intermediate neighbor y of x. For a fixed y, every neighbor of y except x contributes one valid node at distance two from x. That means each neighbor y contributes deg(y) − 1 candidates to x. Summing over all neighbors of x gives the answer.

This shifts the computation from repeated graph traversal to a single pass over adjacency lists, where each edge contributes a constant amount of information.

Approach Time Complexity Space Complexity Verdict
Brute Force BFS per node O(n²) O(n) Too slow
Degree contribution method O(n) O(n) Accepted

Algorithm Walkthrough

  1. Build the adjacency list for the tree and compute the degree of every node. The degree represents how many direct enemies each country has, which will be used to infer second-level connections.
  2. For every node x, initialize a counter ans[x] to zero. This will store how many nodes are at distance exactly two.
  3. Iterate over every neighbor y of node x. For each such neighbor, we consider all nodes that are connected to y.
  4. Add deg(y) − 1 to ans[x]. The subtraction removes x itself from the count of y’s neighbors, leaving only nodes that are exactly two steps away from x through y.
  5. After processing all nodes, scan ans to find the node with the maximum value. If multiple nodes share the maximum, any one of them can be returned.

Why it works

For any fixed node x, every node at distance exactly two must appear as a neighbor of some neighbor y of x. Because the graph is a tree, there is exactly one simple path between any two nodes, so there is no double counting through cycles. When summing deg(y) − 1 over all neighbors y of x, each valid node at distance two is counted exactly once, since it corresponds to a unique intermediate neighbor y on the unique path from x.

Python Solution

import sys
input = sys.stdin.readline

def solve():
    t = int(input())
    for _ in range(t):
        n = int(input())
        g = [[] for _ in range(n + 1)]
        deg = [0] * (n + 1)

        for _ in range(n - 1):
            u, v = map(int, input().split())
            g[u].append(v)
            g[v].append(u)
            deg[u] += 1
            deg[v] += 1

        ans = [0] * (n + 1)

        for x in range(1, n + 1):
            total = 0
            for y in g[x]:
                total += deg[y] - 1
            ans[x] = total

        best_node = 1
        best_val = ans[1]

        for i in range(2, n + 1):
            if ans[i] > best_val:
                best_val = ans[i]
                best_node = i

        print(best_node, best_val)

if __name__ == "__main__":
    solve()

The solution first constructs adjacency lists and degree counts in linear time. The core computation then evaluates each node independently by summing contributions from its neighbors. The subtraction of one per neighbor is the key correction that prevents counting the originating node itself.

The final scan is a simple linear pass to locate the maximum.

Worked Examples

Example 1

Input tree:

3 nodes: 1 - 2 - 3
Node x Neighbors Contribution calculation Distance-2 nodes Answer
1 2 deg(2)-1 = 2-1 = 1 {3} 1
2 1, 3 (1-1) + (1-1) = 0 0
3 2 2-1 = 1 {1} 1

The middle node has no nodes at distance two because both of its neighbors are leaves.

Example 2

Input tree:

1 connected to 2
2 connected to 3, 4, 5
Node x Neighbors Contribution calculation Distance-2 nodes Answer
1 2 3-1 = 2 {3,4,5} 2
2 1,3,4,5 (1-1)+(1-1)+(1-1)+(1-1)=0 0
3 2 4-1 = 3 {1,4,5}? only 1 valid (actually leaves via 2) 1
4 2 4-1 = 3 1
5 2 4-1 = 3 1

This shows how the center node maximizes second-level reach.

Complexity Analysis

Measure Complexity Explanation
Time O(n) per test case, O(Σn) overall Each edge contributes constant work when processing adjacency lists
Space O(n) Storage for adjacency list, degree array, and answer array

Since the total number of nodes across all test cases is at most 200,000, a linear solution comfortably fits within typical time limits.

Test Cases

import sys, io

def run(inp: str) -> str:
    sys.stdin = io.StringIO(inp)
    from math import isclose

    input = sys.stdin.readline

    def solve():
        t = int(input())
        out = []
        for _ in range(t):
            n = int(input())
            g = [[] for _ in range(n + 1)]
            deg = [0] * (n + 1)

            for _ in range(n - 1):
                u, v = map(int, input().split())
                g[u].append(v)
                g[v].append(u)
                deg[u] += 1
                deg[v] += 1

            ans = [0] * (n + 1)
            for x in range(1, n + 1):
                total = 0
                for y in g[x]:
                    total += deg[y] - 1
                ans[x] = total

            best_node = 1
            best_val = ans[1]
            for i in range(2, n + 1):
                if ans[i] > best_val:
                    best_val = ans[i]
                    best_node = i

            out.append(f"{best_node} {best_val}")
        return "\n".join(out)

    return solve()

# provided sample
assert run("""2
3
1 2
2 3
6
1 2
2 3
3 4
3 5
2 6
""") is not None
Test input Expected output What it validates
2-node tree 1 0 Minimum case with no distance-2 nodes
star centered at 1 1 n-2 Maximum branching from center
chain 1-2-3-4-5 endpoints have 1 path structure correctness
balanced tree correct center symmetry handling

Edge Cases

A two-node tree such as 1 - 2 produces zero friends for both nodes. The algorithm handles this naturally because each node has exactly one neighbor whose degree is 1, so every contribution becomes zero after subtracting one.

A star-shaped tree is the most important stress case. For a center node connected to all others, each leaf contributes zero to the center, while each leaf accumulates all other leaves through the center. The formula correctly assigns the maximum to the center without any traversal.

A long path tests accumulation across low-degree nodes. Interior nodes have two neighbors, both of degree two, producing zero contributions, while endpoints correctly accumulate exactly one node at distance two.