Submission #1319374

#TimeUsernameProblemLanguageResultExecution timeMemory
1319374Boycl07Robot (JOI21_ho_t4)C++20
34 / 100
3096 ms44236 KiB
#include <iostream>
#include <vector>
#include <map>
#include <queue>

using namespace std;

typedef long long ll;
const ll INF = 1e18;

struct Edge {
    int to, color;
    ll cost;
    int id;
};

struct State {
    ll d;
    int u, color, edge_idx;
    bool operator>(const State& other) const { return d > other.d; }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, M;
    cin >> N >> M; 

    vector<vector<Edge>> adj(N + 1);
    vector<map<int, ll>> color_sum(N + 1);
    
    for (int i = 0; i < M; ++i) {
        int u, v, c;
        ll p;
        cin >> u >> v >> c >> p; 
        adj[u].push_back({v, c, p, i});
        adj[v].push_back({u, c, p, i});
        color_sum[u][c] += p;
        color_sum[v][c] += p;
    }

    priority_queue<State, vector<State>, greater<State>> pq;
    vector<ll> dist(N + 1, INF);
    vector<ll> dist_edge(M, INF);

    dist[1] = 0; 
    pq.push({0, 1, 0, -1});

    while (!pq.empty()) {
        State top = pq.top();
        pq.pop();

        ll d = top.d;
        int u = top.u;

        // Type 1 State: Arrived at crossing u normally
        if (top.edge_idx == -1) {
            if (d > dist[u]) continue;
            for (auto& e : adj[u]) {
                // Option A: Change only this road's color 
                if (dist[e.to] > d + e.cost) {
                    dist[e.to] = d + e.cost;
                    pq.push({dist[e.to], e.to, 0, -1});
                }
                // Option B: Change all other roads of the same color
                ll cost_all_others = color_sum[u][e.color] - e.cost;
                if (dist[e.to] > d + cost_all_others) {
                    dist[e.to] = d + cost_all_others;
                    pq.push({dist[e.to], e.to, 0, -1});
                }
                // Option C: Move to Type 2 state (carrying the color cost)
                if (dist_edge[e.id] > d) {
                    dist_edge[e.id] = d;
                    pq.push({dist_edge[e.id], e.to, e.color, e.id});
                }
            }
        } 
        // Type 2 State: Arrived at u, but color 'top.color' was "pre-paid" at previous node
        else {
            if (d > dist_edge[top.edge_idx]) continue;
            for (auto& e : adj[u]) {
                if (e.id == top.edge_idx) continue;
                if (e.color == top.color) {
                    ll cost_remaining = color_sum[u][e.color] - e.cost;
                    if (dist[e.to] > d + cost_remaining) {
                        dist[e.to] = d + cost_remaining;
                        pq.push({dist[e.to], e.to, 0, -1});
                    }
                }
            }
        }
    }

    if (dist[N] == INF) cout << -1 << endl;
    else cout << dist[N] << endl; 

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...