JOI 2021 - Robot

Author: Andi Qu

Table of Contents

ExplanationImplementation

Explanation

Lemma: We can always recolour an edge (u,v)(u, v) so that its colour is different from those of the other edges incident to uu and vv.

Proof: If we take away (u,v)(u, v), then there are at most M1M - 1 edges incident to uu and vv. Since there are MM colours in total, there must exist some colour such that none of those edges have it (by the pigeonhole principle). Therefore, we can simply recolour (u,v)(u, v) to that colour.

This means we can define the cost to traverse an edge as:

min(Cost to recolour it,Cost to recolour same-coloured neighbours)\min(\text{Cost to recolour it}, \text{Cost to recolour same-coloured neighbours})

It may be tempting to use Dijkstra's algorithm at this point, but that will unfortunately result in a wrong answer. Consider the following:

  • The robot goes on the path uvwu \rightarrow v \rightarrow w.
  • (u,v)(u, v) and (v,w)(v, w) have the same colour.
  • It's optimal to recolour (u,v)(u, v) when going uvu \rightarrow v, but it's optimal to recolour the same-coloured neighbours of (v,w)(v, w) when going vwv \rightarrow w.

In this case, using Dijkstra's algorithm naively will count the cost to recolour (u,v)(u, v) twice in our answer!

To amend this, let's define two DP arrays instead of just one:

  • dp1[i]\texttt{dp1}[i] is the minimum cost to get to node ii.
  • dp2[i][c]\texttt{dp2}[i][c] is the minimum cost to get to node ii if:
    • The robot just traversed a cc-coloured edge to get to node ii.
    • We're meant to have recoloured that edge, but haven't yet.
    • The robot will definitely leave node ii via another cc-coloured edge and we will recolour all of its same-coloured neighbours.

We can then use Dijkstra's algorithm and some casework to solve this problem in amortized O((N+M)logN)\mathcal O((N + M) \log N) time.

Implementation

Time Complexity: O((N+M)logN)\mathcal O((N + M) \log N)

C++

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll INF = 1e18;
struct Edge {
int to, c;
ll p;
};

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!