Editorial for APIO '08 P2 - Roads
Submitting an official solution before solving the problem yourself is a bannable offence.
We first note one structural property that allows us to use a greedy approach to solve this task. Given a graph , where is the set of villages, and is the set of roads, we color each edge blue if it is a cobblestone road and red otherwise. This task wants to find a spanning tree of that contains exactly blue edges.
Consider any spanning tree . Note that if we consider a subgraph of that contains only blue edges, we get a forest. It is known that for any two forests and , such that has edges, has edges, and , there exists some edge such that remains a forest. (See, e.g., Cormen et al., Chapter 16 on matroids.) This implies that to find a spanning tree with blue edges, we can never make a mistake by taking in wrong blue edges.
With that fact, there are many ways to find a required spanning tree. We present here one solution.
The algorithm has two rounds. First, we try to find a set of "required" blue edges, i.e., these edges must be in the tree to ensure connectivity. We start by finding all connected components of a subgraph containing only red edges. We then greedily add blue edges joining different components so that the graph is connected. These blue edges added in this round form the starting blue edge set . Clearly, if we need more than edges to connect the graph, we can be sure that there is no spanning tree with the required property.
In the second round, we start with a forest with only edges in . We then greedily add blue edges to while maintaining that the resulting graph remains a forest. We keep adding until we get blue edges in . After that, we complete the algorithm by using red edges to join different connected components in .
If we fail in any step, it means that no solution exists.
The main data structure that we use in both rounds is the union-find data structure for maintaining disjoint sets.
In the first round, to find connected components of red edges, we just union every pair of components containing end points of red edges. Before adding blue edges , we call two find subroutines to check if joins two different components. If that's the case, we union both components. In the second round, we may proceed like the second step of the first round.
To analyze the running time, for each round, we call at most unions and finds. Using a set of trees with union-by-rank heuristics ensures that each operation (union or find) runs in time . Thus, the algorithm runs in time .
Comments