제출 #632414

#제출 시각아이디문제언어결과실행 시간메모리
632414colossal_pepeOlympic Bus (JOI20_ho_t4)C++17
100 / 100
874 ms3252 KiB
#include <iostream>
#include <vector>
#include <tuple>
#include <set>
#include <cstring>
using namespace std;

using usi = unsigned int;

const usi INF = 1e8 + 1;
 
int n, m;
vector<tuple<int, int, usi, usi>> edges;
vector<vector<int>> g;
vector<vector<usi>> d;
set<int> imp_edges;
 
usi ssp(int start, int end, int flipped) {
    usi d[n];
    for (int i = 0; i < n; i++) {
        d[i] = INF;
    }
    bool vis[n];
    memset(vis, 0, sizeof vis);
    d[start] = 0;
    for (int _ = 0; _ < n; _++) {
        int u = -1;
        for (int i = 0; i < n; i++) {
            if (not vis[i] and (u == -1 or d[i] < d[u])) u = i;
        }
        for (int i : g[u]) {
            auto [a, b, w, c] = edges[i];
            if (flipped == i) swap(a, b);
            d[b] = min(d[b], d[u] + w);
        }
        vis[u] = 1;
    }
    return d[end];
}
 
void restoreEdges(int u, int start, bool vis[]) {
    vis[u] = 1;
    for (int i : g[u]) {
        auto [a, b, w, c] = edges[i];
        if (not vis[b] and d[start][b] == d[start][u] + w) {
            imp_edges.insert(i);
            restoreEdges(b, start, vis);
        }
    }
}
 
void getImpEdges() {
    bool vis[n];
    memset(vis, 0, sizeof vis);
    restoreEdges(0, 0, vis);
    memset(vis, 0, sizeof vis);
    restoreEdges(n - 1, n - 1, vis);
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n >> m;
    g.resize(n), edges.resize(m);
    d.resize(n, vector<usi>(n, INF));
    for (int i = 0; i < n; i++) {
        d[i][i] = 0;
    }
    for (int i = 0; i < m; i++) {
        auto &[a, b, w, c] = edges[i];
        cin >> a >> b >> w >> c;
        a--, b--;
        g[a].push_back(i);
        g[b].push_back(i);
        d[a][b] = min(d[a][b], w);
    }
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
            }
        }
    }
    getImpEdges();
    // cout << "DUCK : " << endl;
    // for (int i = 0; i < n; i++) {
    //     for (int j = 0; j < n; j++) {
    //         cout << d[i][j] << ' ';
    //     }
    //     cout << endl;
    // }
    // cout << "FUCK : ";
    // for (int i : imp_edges) {
    //     cout << i << ' ';
    // }
    // cout << endl;
    usi ans;
    if (d[0][n - 1] == INF or d[n - 1][0] == INF) ans = 4294967295;
    else ans = d[0][n - 1] + d[n - 1][0]; // 0 0
    for (int i = 0; i < m; i++) {
        auto [a, b, w, c] = edges[i];
        if (imp_edges.find(i) != imp_edges.end()) {
            usi x = ssp(0, n - 1, i), y = ssp(n - 1, 0, i);
            if (x != INF and y != INF) ans = min(ans, x + y + c);
            continue;
        }
        if (d[0][n - 1] != INF and d[n - 1][a] != INF and d[b][0] != INF)
            ans = min(ans, d[0][n - 1] + d[n - 1][a] + w + d[b][0] + c); // 0 1
        if (d[0][n - 1] != INF and d[n - 1][b] != INF and d[a][0] != INF)
            ans = min(ans, d[0][n - 1] + d[n - 1][b] + w + d[a][0] + c); // 0 2
        if (d[0][a] != INF and d[b][n - 1] != INF and d[n - 1][0] != INF)
            ans = min(ans, d[0][a] + w + d[b][n - 1] + d[n - 1][0] + c); // 1 0
        if (d[0][a] != INF and d[b][n - 1] != INF and d[n - 1][a] != INF and d[b][0] != INF)
            ans = min(ans, d[0][a] + w + d[b][n - 1] + d[n - 1][a] + w + d[b][0] + c); // 1 1
        if (d[0][a] != INF and d[b][n - 1] != INF and d[n - 1][b] != INF and d[a][0] != INF)
            ans = min(ans, d[0][a] + w + d[b][n - 1] + d[n - 1][b] + w + d[a][0] + c); // 1 2
        if (d[0][b] != INF and d[a][n - 1] != INF and d[n - 1][0] != INF)
            ans = min(ans, d[0][b] + w + d[a][n - 1] + d[n - 1][0] + c); // 2 0
        if (d[0][b] != INF and d[a][n - 1] != INF and d[n - 1][a] != INF and d[b][0] != INF)
            ans = min(ans, d[0][b] + w + d[a][n - 1] + d[n - 1][a] + w + d[b][0] + c); // 2 1
        if (d[0][b] != INF and d[a][n - 1] != INF and d[n - 1][b] != INF and d[a][0] != INF)
            ans = min(ans, d[0][b] + w + d[a][n - 1] + d[n - 1][b] + w + d[a][0] + c); // 2 2
    }
    if (ans == 4294967295) cout << -1 << '\n';
    else cout << ans << '\n';
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...