Submission #670204

#TimeUsernameProblemLanguageResultExecution timeMemory
670204ForestedRelay Marathon (NOI20_relaymarathon)C++17
100 / 100
2522 ms232660 KiB
#ifndef LOCAL
#define FAST_IO
#endif

// ============
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define OVERRIDE(a, b, c, d, ...) d
#define REP2(i, n) for (i32 i = 0; i < (i32) (n); ++i)
#define REP3(i, m, n) for (i32 i = (i32) (m); i < (i32) (n); ++i)
#define REP(...) OVERRIDE(__VA_ARGS__, REP3, REP2)(__VA_ARGS__)
#define PER(i, n) for (i32 i = (i32) (n) - 1; i >= 0; --i)
#define ALL(x) begin(x), end(x)

using namespace std;

using u32 = unsigned int;
using u64 = unsigned long long;
using u128 = __uint128_t;
using i32 = signed int;
using i64 = signed long long;
using i128 = __int128_t;
using f64 = double;
using f80 = long double;

template <typename T>
using Vec = vector<T>;

template <typename T>
bool chmin(T &x, const T &y) {
    if (x > y) {
        x = y;
        return true;
    }
    return false;
}
template <typename T>
bool chmax(T &x, const T &y) {
    if (x < y) {
        x = y;
        return true;
    }
    return false;
}

istream &operator>>(istream &is, i128 &x) {
    i64 v;
    is >> v;
    x = v;
    return is;
}
ostream &operator<<(ostream &os, i128 x) {
    os << (i64) x;
    return os;
}
istream &operator>>(istream &is, u128 &x) {
    u64 v;
    is >> v;
    x = v;
    return is;
}
ostream &operator<<(ostream &os, u128 x) {
    os << (u64) x;
    return os;
}

[[maybe_unused]] constexpr i32 INF = 1000000100;
[[maybe_unused]] constexpr i64 INF64 = 3000000000000000100;
struct SetUpIO {
    SetUpIO() {
#ifdef FAST_IO
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
#endif
        cout << fixed << setprecision(15);
    }
} set_up_io;
// ============

#ifdef DEBUGF
#else
#define DBG(x) (void) 0
#endif

constexpr i32 SZ = 4;

bool update(array<Vec<pair<i64, i32>>, SZ> &dist, i32 v, i64 d, i32 f) {
    REP(i, SZ) {
        if (dist[i][v].second == f) {
            if (d >= dist[i][v].first) {
                return false;
            }
            dist[i][v].first = d;
            i32 cur = i;
            while (cur > 0 && dist[cur - 1][v].first > dist[cur][v].first) {
                swap(dist[cur - 1][v], dist[cur][v]);
                --cur;
            }
            return true;
        }
    }
    if (d >= dist[SZ - 1][v].first) {
        return false;
    }
    dist[SZ - 1][v] = pair<i64, i32>(d, f);
    i32 cur = SZ - 1;
    while (cur > 0 && dist[cur - 1][v].first > dist[cur][v].first) {
        swap(dist[cur - 1][v], dist[cur][v]);
        --cur;
    }
    return true;
}

int main() {
    i32 n, m, k;
    cin >> n >> m >> k;
    Vec<Vec<pair<i32, i64>>> g(n);
    REP(ei, m) {
        i32 u, v, w;
        cin >> u >> v >> w;
        --u;
        --v;
        g[u].emplace_back(v, w);
        g[v].emplace_back(u, w);
    }
    Vec<i32> a(k);
    REP(i, k) {
        cin >> a[i];
        --a[i];
    }
    
    array<Vec<pair<i64, i32>>, SZ> dist;
    fill(ALL(dist), Vec<pair<i64, i32>>(n, pair<i64, i32>(INF64, -1)));
    priority_queue<tuple<i64, i32, i32>> pq;
    REP(i, k) {
        dist[0][a[i]] = pair<i64, i32>(0, i);
        pq.emplace(0, i, a[i]);
    }
    while (!pq.empty()) {
        auto [d, f, v] = pq.top();
        pq.pop();
        d *= -1;
        bool found = false;
        REP(i, SZ) {
            if (dist[i][v] == pair<i64, i32>(d, f)) {
                found = true;
            }
        }
        if (!found) {
            continue;
        }
        for (auto &[u, w] : g[v]) {
            if (update(dist, u, d + w, f)) {
                pq.emplace(-(d + w), f, u);
            }
        }
    }
    
    array<Vec<pair<i64, i32>>, SZ> adist;
    fill(ALL(adist), Vec<pair<i64, i32>>(k, pair<i64, i32>(INF64, -1)));
    REP(i, 4) REP(j, k) {
        adist[i][j] = dist[i][a[j]];
    }
    
    i64 closest = INF64;
    i32 cu = -1, cv = -1;
    REP(i, k) {
        if (chmin(closest, adist[1][i].first)) {
            cu = i;
            cv = adist[1][i].second;
        }
    }
    
    i64 exmin = INF64;
    REP(i, k) {
        if (i == cu || i == cv) {
            continue;
        }
        REP(j, 1, 4) {
            if (adist[j][i].second != cu && adist[j][i].second != cv) {
                chmin(exmin, adist[j][i].first);
            }
        }
    }
    
    i64 ans = closest + exmin;
    
    REP(i, 2, 4) REP(j, 2, 4) {
        if (adist[i][cu].second != adist[j][cv].second) {
            chmin(ans, adist[i][cu].first + adist[j][cv].first);
        }
    }
    
    cout << ans << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...