제출 #1319354

#제출 시각아이디문제언어결과실행 시간메모리
1319354Boycl07Robot (JOI21_ho_t4)C++20
34 / 100
3098 ms58688 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>

using namespace std;

/** * Cấu trúc lưu trữ thông tin cạnh:
 * to: Đỉnh đến
 * color: Màu của cạnh
 * cost: Chi phí thay đổi màu (P_i)
 */
struct Edge {
    int to, color, cost;
};

struct State {
    long long dist;
    int u, color;

    // Priority queue cần min-heap
    bool operator>(const State& other) const {
        return dist > other.dist;
    }
};

const long long INF = 1e18;
vector<Edge> adj[200005];
map<int, long long> sum_cost[200005]; // Tổng P_i của các cạnh cùng màu tại mỗi đỉnh
map<int, long long> dist[200005];     // dist[u][color] (color=0 là trạng thái mặc định)

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

    int n, m;
    cin >> n >> m;

    for (int i = 0; i < m; ++i) {
        int u, v, c, p;
        cin >> u >> v >> c >> p;
        adj[u].push_back({v, c, p});
        adj[v].push_back({u, c, p});
        sum_cost[u][c] += p;
        sum_cost[v][c] += p;
    }

    priority_queue<State, vector<State>, greater<State>> pq;

    // Xuất phát từ đỉnh 1, trạng thái không màu (0)
    dist[1][0] = 0;
    pq.push({0, 1, 0});

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

        int u = top.u;
        int c = top.color;
        long long d = top.dist;

        if (d > dist[u][c]) continue;

        if (c == 0) {
            // Đang ở trạng thái bình thường tại đỉnh u
            for (auto& e : adj[u]) {
                // Cách 1: Đổi màu duy nhất cạnh này (cost = P_i)
                if (!dist[e.to].count(0) || dist[e.to][0] > d + e.cost) {
                    dist[e.to][0] = d + e.cost;
                    pq.push({dist[e.to][0], e.to, 0});
                }

                // Cách 2: Đổi màu tất cả các cạnh khác cùng màu e.color (cost = Sum - P_i)
                long long cost2 = sum_cost[u][e.color] - e.cost;
                if (!dist[e.to].count(0) || dist[e.to][0] > d + cost2) {
                    dist[e.to][0] = d + cost2;
                    pq.push({dist[e.to][0], e.to, 0});
                }

                // Cách 3: Chuyển sang trạng thái đặc biệt (v, c) để xử lý tiếp
                // Không mất phí lúc này, phí sẽ tính ở bước kế tiếp
                if (!dist[e.to].count(e.color) || dist[e.to][e.color] > d) {
                    dist[e.to][e.color] = d;
                    pq.push({dist[e.to][e.color], e.to, e.color});
                }
            }
        } else {
            // Đang ở trạng thái đặc biệt: vừa đến u bằng cạnh có màu c (Strategy B)
            for (auto& e : adj[u]) {
                if (e.color == c) {
                    // Tiếp tục đổi các cạnh còn lại của màu c (trừ cạnh vừa đi qua)
                    long long cost = sum_cost[u][c] - e.cost;
                    if (!dist[e.to].count(0) || dist[e.to][0] > d + cost) {
                        dist[e.to][0] = d + cost;
                        pq.push({dist[e.to][0], e.to, 0});
                    }
                }
            }
        }
    }

    if (!dist[n].count(0)) cout << -1 << endl;
    else cout << dist[n][0] << endl;

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