Table of Contents

ExplanationImplementation

Explanation

At first glance, it seems Kruskal's would be more appropriate for this problem, so let's use that.

Let's first give each child their own DSU data structure to store which cities are connected with their railroads, and then iterate through the railroads through decreasing order of price, giving each railroad to the first child that can accept it. This is effectively the same as going through each child one at a time and constructing a maximum spanning tree for each of them individually.

However, linearly iterating through the entire list of DSUs would result in a runtime of about O(KM)\mathcal{O}(KM), which is too slow given the bounds.

To quickly find the first child that can accept a railroad, let's try using binary search! But for binary search to actually work, we first need to prove the following:

No matter what railroad we're processing, all children after the first child that can accept the current railroad can also accept said railroad, while all children before that child cannot.

For this to hold, each DSU's connected components must be obtainable from the one after by adding some edges (0 edges is fine too). This is obviously true for when we start, so now all we have to prove is that giving a railroad to the first child that can accept it will preserve this relation.

Say we had two children that are adjacent in seniority: cic_i and ci+1c_{i+1}, with cic_i being older, and ci+1c_{i+1} being the first child that can accept the current railroad. If giving ci+1c_{i+1} the railroad would make it so that obtaining cic_i from the new ci+1c_{i+1} is impossible, then that would mean the railroad would connect some two components of cic_i and thus also mean that cic_i should be the first to accept the railroad, not ci+1c_{i+1}.

Using binary search reduces O(KM)\mathcal{O}(KM) to O(KlogM)\mathcal{O}(K \log M), which runs in time.

Implementation

Time Complexity: O(KlogM)\mathcal{O}(K\log M) for each of TT test cases

C++

#include <algorithm>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
Code Snippet: DSU (Click to expand)

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!