Submission #1178491

#TimeUsernameProblemLanguageResultExecution timeMemory
1178491_callmelucianRelay Marathon (NOI20_relaymarathon)C++17
42 / 100
6087 ms273904 KiB
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using pl = pair<ll,ll>;
using pii = pair<int,int>;
using tpl = tuple<int,int,int>;

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

const int mn = 1e5 + 5;
const int maxStage = 4;

int spec[mn], dist[maxStage][mn], optSource[maxStage][mn], n, m, k;
vector<pii> adj[mn], path[mn];
vector<int> visSource[mn];
priority_queue<tpl> pq;

struct IT {
    vector<int> tr;
    IT (int sz) : tr(4 * sz, INT_MAX) {}

    void update (int pos, int val, int k, int l, int r) {
        for (; l < r;) {
            int mid = (l + r) >> 1;
            if (pos <= mid) k <<= 1, r = mid;
            else k <<= 1, k |= 1, l = mid + 1;
        }
        tr[k] = min(tr[k], val);
        for (k >>= 1; k >= 1; k >>= 1)
            tr[k] = min(tr[k << 1], tr[k << 1 | 1]);
    }

    int query (int a, int b, int k, int l, int r) {
        if (b < l || r < a) return INT_MAX;
        if (a <= l && r <= b) return tr[k];
        int mid = (l + r) >> 1;
        return min(query(a, b, k << 1, l, mid), query(a, b, k << 1 | 1, mid + 1, r));
    }
};

struct ITRange {
    vector<int> lazy;
    ITRange (int sz) : lazy(4 * sz, INT_MAX) {}

    void update (int a, int b, int val, int k, int l, int r) {
        if (b < l || r < a) return;
        if (a <= l && r <= b) return lazy[k] = min(lazy[k], val), void();
        int mid = (l + r) >> 1;
        update(a, b, val, k << 1, l, mid);
        update(a, b, val, k << 1 | 1, mid + 1, r);
    }

    int query (int pos, int k, int l, int r) {
        int ans = lazy[k];
        for (; l < r;) {
            int mid = (l + r) >> 1;
            if (pos <= mid) k <<= 1, r = mid;
            else k <<= 1, k |= 1, l = mid + 1;
            ans = min(ans, lazy[k]);
        }
        return ans;
    }
};

void addPath (int u, int v, int w) {
    if (w == INT_MAX) return;
    path[max(u, v)].emplace_back(min(u, v), w);
}

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

    /// read input & preprocess
    cin >> n >> m >> k;
    while (m--) {
        int a, b, c; cin >> a >> b >> c;
        adj[a].emplace_back(b, c);
        adj[b].emplace_back(a, c);
    }
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < maxStage; j++) dist[j][i] = INT_MAX;
    for (int i = 1; i <= k; i++) {
        cin >> spec[i];
        pq.emplace(0, spec[i], spec[i]);
    }

    /// multi-core dijkstra
    int threshold = 0;
    while (pq.size() && threshold < 5 * n) {
        int dst, u, source; tie(dst, u, source) = pq.top(); pq.pop();
        if (visSource[u].size() >= maxStage || find(all(visSource[u]), source) != visSource[u].end()) continue;

        int stage = visSource[u].size();
        dst = -dst, dist[stage][u] = dst, optSource[stage][u] = source;
        visSource[u].push_back(source), threshold++;

        for (pii item : adj[u]) {
            int v, w; tie(v, w) = item;
            if (dst + w < dist[maxStage - 1][v])
                if (find(all(visSource[v]), source) == visSource[v].end()) pq.emplace(-(dst + w), v, source);
        }
    }

    /// solve
    for (int i = 1; i <= k; i++) {
        int u = spec[i];
        for (int j = 1; j < maxStage; j++)
            addPath(u, optSource[j][u], dist[j][u]);
    }

    int ans = INT_MAX;
    IT treeLeft(n), treeRight(n);
    ITRange treeRange(n);

    for (int i = 1; i <= n; i++) {
        for (pii item : path[i]) {
            int j, w; tie(j, w) = item;
            int cur = min({treeRight.query(1, j - 1, 1, 1, n),
                           treeLeft.query(j + 1, n, 1, 1, n),
                           treeRange.query(j, 1, 1, n)});
            if (cur != INT_MAX) ans = min(ans, cur + w);
        }
        for (pii item : path[i]) {
            int j, w; tie(j, w) = item;
            treeLeft.update(j, w, 1, 1, n);
            treeRight.update(i, w, 1, 1, n);
            if (j + 1 <= i - 1)
                treeRange.update(j + 1, i - 1, w, 1, 1, n);
        }
    }
    cout << (ans == INT_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...