Skip to content

USACO 2023 February Contest Silver Division - Moo Route II#

Problem link: here

Solution Author: Stefan Dascalescu

Problem Solution#

We can apply a BFS traversal, in the style of the Bellman-Ford algorithm for shortest paths, but we need to relax the answer only once for each edge.

Source code#

The source code in C++ can be seen below.

#include <bits/stdc++.h>
using namespace std;

#define fi first
#define se second

const int MOD = 1e9 + 7;
const int INF = (1 << 30);
const int ALP = 26;
const long long LL_INF = (1LL << 60);

const int MAX_N = 2e5;

struct Edge {
    int depart, v, arrive;
};

int N, M;
int A[MAX_N + 5];
int dist[MAX_N + 5];
vector<Edge> adjList[MAX_N + 5];

bool cmp(Edge X, Edge Y) { 
    return X.depart < Y.depart; 
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> N >> M;
    for (int i = 1; i <= M; i++) {
        int u, depart, v, arrive;
        cin >> u >> depart >> v >> arrive;
        adjList[u].push_back({depart, v, arrive});
    }
    for (int i = 1; i <= N; i++) {
        dist[i] = INF;
        cin >> A[i];
    }
    dist[1] = 0;
    for (int u = 1; u <= N; u++) {
        for (auto &[depart, v, arrive] : adjList[u]) {
            depart -= A[u];
        }
        sort(adjList[u].begin(), adjList[u].end(), cmp);
    }
    queue<Edge> q;
    for (auto &t : adjList[1]) {
        q.push(t);
    }
    while (!q.empty()) {
        int v = q.front().v;
        int arrive = q.front().arrive;
        q.pop();
        dist[v] = min(dist[v], arrive);
        while (!adjList[v].empty() && adjList[v].back().depart >= arrive) {
            q.push(adjList[v].back());
            adjList[v].pop_back();
        }
    }
    for (int i = 1; i <= N; i++) {
        cout << (dist[i] == INF ? -1 : dist[i]) << "\n";
    }
}