Table of Contents

ExplanationImplementation

Explanation

  1. Use Dijkstra's to calculate distances from ss, uu, and vv.
  2. Consider a subset of directed edges where each directed edge is part of a shortest path from ss to tt. Note that this subset is a DAG, and can be found by keeping track of the parents of every node when running Dijkstra's with ss as the starting node.
  3. An optimal path will either be in the form uxyvu \rightarrow x \rightarrow y \rightarrow v or vxyuv \rightarrow x \rightarrow y \rightarrow u, where xyx \rightarrow y is a path on the DAG. Note that any path on the DAG is a valid commuter pass option.
  4. Without loss of generality, assume that our path has the form uxyvu \rightarrow x \rightarrow y \rightarrow v.
  5. Define dp1(i)\text{dp}_1(i) as the minimum distance from uu to any node xx such that xx is on a path from ss to ii in the DAG.
  6. Define dp2(i)\text{dp}_2(i) as the minimum distance from uu to vv if the commuter pass edges used are on a path from ss to ii in the DAG.
  7. For each parent of a node ii, our transitions are:
    dp1(i)=min ⁣{dp1(i),  distu(i),  dp1(pari)},dp2(i)=min ⁣{dp2(i),  dp1(i)+distv(i),  dp2(pari)}.\begin{aligned} \text{dp}_1(i) &= \min\!\left\{ \text{dp}_1(i),\; \text{dist}_u(i),\; \text{dp}_1(\text{par}_i) \right\}, \\ \text{dp}_2(i) &= \min\!\left\{ \text{dp}_2(i),\; \text{dp}_1(i) + \text{dist}_v(i),\; \text{dp}_2(\text{par}_i) \right\}. \end{aligned}
  8. If the source node is ss, then the answer is dp2(t)\text{dp}_2(t). To handle the case where the optimal path has the form vxyuv \rightarrow x \rightarrow y \rightarrow u, we repeat the algorithm for the source node tt.
  9. Alternatively, the answer could be the distance from uu to vv without using the commuter pass.

Implementation

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

C++

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
vector<pair<ll, ll>> graph[100001];
ll du[100001], dv[100001], ds[100001], dp[2][100001], ans;
bool visited[100001];
void dijkstra1(ll start, ll arr[]) {
fill(visited, visited + 100001, false);

Alternatively, Nathan's implementation. Note that the DP definitions in Nathan's implementation are slightly different than above.

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!