Baltic OI 2017 - Toll

Author: Andi Qu

Table of Contents

SolutionImplementation

Official Analysis

Solution

Split the graph into N/KN / K "layers" with KK nodes each. Notice how this graph somewhat resembles a neural network.

Graph from the sample

Let dp[a][b][x][y]dp[a][b][x][y] denote the minimum cost of a path between nodes Ka+xKa + x to Kb+yKb + y.

For any triple a<b<ca < b < c, the following recurrence holds:

dp[a][c][x][y]=minz[0,K)(dp[a][b][x][z]+dp[b][c][z][y])dp[a][c][x][y] = \min_{z \in [0, K)} (dp[a][b][x][z] + dp[b][c][z][y])

This is known as the (min,+)(\min,+) product.

To finish, we can use any algorithm that allows us to quickly answer static range queries (ex. divide & conquer). Another approach is to use a sparse table. Instead of storing each DP state, we can store only dp[i][i+2j][x][y]dp[i][i + 2^j][x][y] for each ii, jj, xx, and yy. Then we can find the value of dp[A/K][B/K][A%K][B%K]dp[\lfloor A / K \rfloor][\lfloor B / K \rfloor][A \% K][B \% K] in O(K2logN)\mathcal{O}(K^2 \log N) time per query with binary jumping. This gives a time complexity of O(K2(N+O)logN)\mathcal{O}(K^2(N+O)\log N).

Implementation

O(K3logN)\mathcal{O}(K^3 \log N) per query. We can reduce this to O(K2logN)\mathcal{O}(K^2 \log N) per query by only storing the a % k-th row of ans.

#include <bits/stdc++.h>
using namespace std;
int k, n, m, o;
int dp[50000][17][5][5], ans[5][5], tmp[5][5];
void combine(int target[5][5], int a[5][5], int b[5][5]) {
for (int x = 0; x < k; x++) {
for (int y = 0; y < k; y++) {
for (int z = 0; z < k; z++) {

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!