제출 #1088785

#제출 시각아이디문제언어결과실행 시간메모리
1088785_callmelucianOlympic Bus (JOI20_ho_t4)C++14
100 / 100
333 ms4956 KiB
/*
    If you're looking at my code for solution,
    your brute-force code with a bit optimization is the solution.
*/

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

typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pl;
typedef pair<int,int> pii;
typedef tuple<int,int,int> tt;

#define all(a) a.begin(), a.end()
#define filter(a) a.erase(unique(all(a)), a.end())

const int E = 5e4 + 4;
const int mn = 202;

mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

int direct[E], a[E], b[E], cost[E], revCost[E], n;
ll distanc[mn][mn], dist[mn];
vector<tt> adj[mn];
bool vis[mn];

ll dijkstra (int s, int t) {
    for (int i = 1; i <= n; i++) dist[i] = LLONG_MAX, vis[i] = 0;
    dist[s] = 0;

    priority_queue<pl> pq; pq.emplace(0, s);
    while (pq.size()) {
        int u = pq.top().second; pq.pop();
        if (vis[u]) continue;
        if (u == t) return dist[t];
        vis[u] = 1;
        for (tt it : adj[u]) {
            int v, id, way; tie(v, id, way) = it;
            if (way != direct[id]) continue;
            if (dist[u] + cost[id] < dist[v]) {
                dist[v] = dist[u] + cost[id];
                pq.emplace(-dist[v], v);
            }
        }
    }
    return LLONG_MAX;
}

ll add (ll a, ll b) {
    return (max(a, b) == LLONG_MAX ? LLONG_MAX : a + b);
}

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

    int m; cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            distanc[i][j] = (i == j ? 0 : LLONG_MAX);

    for (int i = 0; i < m; i++) {
        cin >> a[i] >> b[i] >> cost[i] >> revCost[i];
        adj[a[i]].emplace_back(b[i], i, 0);
        adj[b[i]].emplace_back(a[i], i, 1);
        distanc[a[i]][b[i]] = min(distanc[a[i]][b[i]], (ll)cost[i]);
    }

    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                distanc[i][j] = min(distanc[i][j], add(distanc[i][k], distanc[k][j]));

    vector<int> cand(m);
    for (int i = 0; i < m; i++) cand[i] = i;
    shuffle(all(cand), rng);

    ll ans = add(distanc[1][n], distanc[n][1]);
    for (int i : cand) {
        ll tryOTN = min(distanc[1][n], add(add(distanc[1][b[i]], cost[i]), distanc[a[i]][n]));
        ll tryNTO = min(distanc[n][1], add(add(distanc[n][b[i]], cost[i]), distanc[a[i]][1]));
        if (add(add(tryOTN, tryNTO), revCost[i]) < ans) { // only optimize when possible
            direct[i] = 1;
            ll dist = add(dijkstra(1, n), dijkstra(n, 1));
            ans = min(ans, add(dist, revCost[i]));
            direct[i] = 0;
        }
    }
    cout << (ans == LLONG_MAX ? -1 : ans);

    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...