Solution 1 - Kruskal's

Official Analysis (Java)

Explanation

We first notice that movement is defined in terms of portals, so we mainly care about how the portals are connected.

Let's consider the undirected multigraph GG with 2N2N nodes such that:

  • Every portal in the original graph corresponds to a node in GG
  • Every node vv in the original graph corresponds to edges pv,0pv,1p_{v,0} \leftrightarrow p_{v,1} and pv,2pv,3p_{v,2} \leftrightarrow p_{v,3} in GG

We observe that each node in GG has degree exactly two, so GG is a union of disjoint cycles. Thus, our goal is to join all nodes in GG into a single cycle.

Let's suppose that portals pv,0p_{v,0} and pv,1p_{v,1} are not contained within the same cycle as pv,2p_{v,2} and pv,3p_{v,3} in GG.

Then, by permuting the portals adjacent to node vv such that the adjacency list becomes pv,0,pv,2,pv,1,pv,3p_{v,0}, p_{v,2}, p_{v,1}, p_{v,3}, we can combine all of pv,0,pv,1,pv,2,pv,3p_{v,0}, p_{v,1}, p_{v,2}, p_{v,3} into a single cycle. Essentially, each node can unite two cycles.

Notice that by replacing "cycles" with "connected components" above, we are encouraged to find a Minimum Spanning Tree (MST). In other words, we wish to unite all disjoint connected components such that GG becomes connected.

Now, let's consider the graph GG' with the same nodes as GG and the following costs:

  • For each node vv, edges pv,0pv,1p_{v,0} \leftrightarrow p_{v,1} and pv,2pv,3p_{v,2} \leftrightarrow p_{v,3} have cost 00
  • For each node vv, edge pv,0pv,2p_{v,0} \leftrightarrow p_{v,2} has cost cvc_v moonies

Specifically, the answer is the cost of the MST of GG', which can be found using Kruskal's algorithm or Prim's algorithm.

Implementation

Time Complexity: O(NlogN)\mathcal{O}(N\log N)

C++

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
struct Edge {
int from, to, cost;
};
const int MAX_N = 100000;
int parent[MAX_N * 2];

Solution 2 - Prim's

Time Complexity: O(NlogN)\mathcal{O}(N\log N)

C++

#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int MAX_N = 100000;
struct Node {
int vertex, cost;
bool operator>(Node other) const { return cost > other.cost; }
};

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!