13702022-07-27 20:37:44mraronKészülés a Maratonra 2cpp14Accepted 100/100804ms52880 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
constexpr ll INF = 1e18;
constexpr int MAXN = 505;

vector<pair<int, int>> grafo[MAXN];
ll dist[MAXN][MAXN];
bool vis[MAXN];

void dijkstra(int s) {
    memset(dist[s], 0x3f, sizeof(dist[0]));
    memset(vis, 0, sizeof(vis));

    priority_queue<pair<ll, int>> Q;
    Q.emplace(0, s);
    dist[s][s] = 0;

    while (!Q.empty()) {
        int u = Q.top().second;
        Q.pop();
        if (vis[u]) continue;
        vis[u] = true;
        for (auto [v, w] : grafo[u]) {
            ll dd = dist[s][u] + w;
            if (dd < dist[s][v]) {
                dist[s][v] = dd;
                Q.emplace(-dd, v);
            }
        }
    }
}


struct Blossom {
    struct edge {
        int u, v;
        ll w;
    } g[MAXN * 2][MAXN * 2];
    int n, n_x, match[MAXN * 2], slack[MAXN * 2], st[MAXN * 2], pa[MAXN * 2], flower_from[MAXN * 2][MAXN * 2], S[MAXN * 2], vis[MAXN * 2];
    ll lab[MAXN * 2];
    ll dist(edge const& e) { return lab[e.u] + lab[e.v] - g[e.u][e.v].w * 2; }
    vector<int> flower[MAXN * 2];
    deque<int> q;
    Blossom() {}
    Blossom(int _n) {
        n = _n;
        q = deque<int>();
        for (int u = 1; u <= n * 2; ++u) {
            match[u] = slack[u] = st[u] = pa[u] = S[u] = vis[u] = lab[u] = 0;
            for (int v = 1; v <= n * 2; ++v) {
                g[u][v] = edge{u, v, 0};
                flower_from[u][v] = 0;
            }
            flower[u].clear();
        }
    }
    void add_edge(int u, int v, ll w) {
        ++u;
        ++v;
        g[u][v].w = max(g[u][v].w, w);
        g[v][u].w = max(g[v][u].w, w);
    }
    void update_slack(int u, int x) {
        if (!slack[x] || dist(g[u][x]) < dist(g[slack[x]][x])) slack[x] = u;
    }
    void set_slack(int x) {
        slack[x] = 0;
        for (int u = 1; u <= n; ++u) {
            if (g[u][x].w > 0 && st[u] != x && S[st[u]] == 0) update_slack(u, x);
        }
    }
    void q_push(int x) {
        if (x <= n) return q.push_back(x);
        for (int i = 0; i < (int)flower[x].size(); i++) q_push(flower[x][i]);
    }
    void set_st(int x, int b) {
        st[x] = b;
        if (x <= n) return;
        for (int i = 0; i < (int)flower[x].size(); ++i) set_st(flower[x][i], b);
    }
    int get_pr(int b, int xr) {
        int pr = find(flower[b].begin(), flower[b].end(), xr) - flower[b].begin();
        if (pr % 2 == 1) {
            reverse(flower[b].begin() + 1, flower[b].end());
            return (int)flower[b].size() - pr;
        } else
            return pr;
    }
    void set_match(int u, int v) {
        match[u] = g[u][v].v;
        if (u <= n) return;
        edge e = g[u][v];
        int xr = flower_from[u][e.u], pr = get_pr(u, xr);
        for (int i = 0; i < pr; ++i) set_match(flower[u][i], flower[u][i ^ 1]);
        set_match(xr, v);
        rotate(flower[u].begin(), flower[u].begin() + pr, flower[u].end());
    }
    void augment(int u, int v) {
        int xnv = st[match[u]];
        set_match(u, v);
        if (!xnv) return;
        set_match(xnv, st[pa[xnv]]);
        augment(st[pa[xnv]], xnv);
    }
    int get_lca(int u, int v) {
        static int t = 0;
        for (++t; u || v; swap(u, v)) {
            if (u == 0) continue;
            if (vis[u] == t) return u;
            vis[u] = t;
            u = st[match[u]];
            if (u) u = st[pa[u]];
        }
        return 0;
    }
    void add_blossom(int u, int lca, int v) {
        int b = n + 1;
        while (b <= n_x && st[b]) ++b;
        if (b > n_x) ++n_x;
        lab[b] = 0, S[b] = 0;
        match[b] = match[lca];
        flower[b].clear();
        flower[b].push_back(lca);
        for (int x = u, y; x != lca; x = st[pa[y]]) {
            flower[b].push_back(x), flower[b].push_back(y = st[match[x]]), q_push(y);
        }
        reverse(flower[b].begin() + 1, flower[b].end());
        for (int x = v, y; x != lca; x = st[pa[y]]) {
            flower[b].push_back(x), flower[b].push_back(y = st[match[x]]), q_push(y);
        }
        set_st(b, b);
        for (int x = 1; x <= n_x; ++x) g[b][x].w = g[x][b].w = 0;
        for (int x = 1; x <= n; ++x) flower_from[b][x] = 0;
        for (int i = 0; i < (int)flower[b].size(); ++i) {
            int xs = flower[b][i];
            for (int x = 1; x <= n_x; ++x) {
                if (g[b][x].w == 0 || dist(g[xs][x]) < dist(g[b][x])) g[b][x] = g[xs][x], g[x][b] = g[x][xs];
            }
            for (int x = 1; x <= n; ++x) {
                if (flower_from[xs][x]) flower_from[b][x] = xs;
            }
        }
        set_slack(b);
    }
    void expand_blossom(int b) {  // S[b] == 1
        for (int i = 0; i < (int)flower[b].size(); ++i) set_st(flower[b][i], flower[b][i]);
        int xr = flower_from[b][g[b][pa[b]].u], pr = get_pr(b, xr);
        for (int i = 0; i < pr; i += 2) {
            int xs = flower[b][i], xns = flower[b][i + 1];
            pa[xs] = g[xns][xs].u;
            S[xs] = 1, S[xns] = 0;
            slack[xs] = 0, set_slack(xns);
            q_push(xns);
        }
        S[xr] = 1, pa[xr] = pa[b];
        for (int i = pr + 1; i < (int)flower[b].size(); ++i) {
            int xs = flower[b][i];
            S[xs] = -1, set_slack(xs);
        }
        st[b] = 0;
    }
    bool on_found_edge(const edge& e) {
        int u = st[e.u], v = st[e.v];
        if (S[v] == -1) {
            pa[v] = e.u, S[v] = 1;
            int nu = st[match[v]];
            slack[v] = slack[nu] = 0;
            S[nu] = 0, q_push(nu);
        } else if (S[v] == 0) {
            int lca = get_lca(u, v);
            if (!lca)
                return augment(u, v), augment(v, u), 1;
            else
                add_blossom(u, lca, v);
        }
        return 0;
    }
    bool matching() {
        fill(S, S + n_x + 1, -1), fill(slack, slack + n_x + 1, 0);
        q.clear();
        for (int x = 1; x <= n_x; ++x) {
            if (st[x] == x && !match[x]) pa[x] = 0, S[x] = 0, q_push(x);
        }
        if (q.empty()) return 0;
        for (;;) {
            while ((int)q.size()) {
                int u = q.front();
                q.pop_front();
                if (S[st[u]] == 1) continue;
                for (int v = 1; v <= n; ++v) {
                    if (g[u][v].w > 0 && st[u] != st[v]) {
                        if (dist(g[u][v]) == 0) {
                            if (on_found_edge(g[u][v])) return 1;
                        } else
                            update_slack(u, st[v]);
                    }
                }
            }
            ll d = INF;
            for (int b = n + 1; b <= n_x; ++b) {
                if (st[b] == b && S[b] == 1) d = min(d, lab[b] / 2);
            }
            for (int x = 1; x <= n_x; ++x) {
                if (st[x] == x && slack[x]) {
                    if (S[x] == -1)
                        d = min(d, dist(g[slack[x]][x]));
                    else if (S[x] == 0)
                        d = min(d, dist(g[slack[x]][x]) / 2);
                }
            }
            for (int u = 1; u <= n; ++u) {
                if (S[st[u]] == 0) {
                    if (lab[u] <= d) return 0;
                    lab[u] -= d;
                } else if (S[st[u]] == 1)
                    lab[u] += d;
            }
            for (int b = n + 1; b <= n_x; ++b) {
                if (st[b] == b) {
                    if (S[st[b]] == 0)
                        lab[b] += d * 2;
                    else if (S[st[b]] == 1)
                        lab[b] -= d * 2;
                }
            }
            q.clear();
            for (int x = 1; x <= n_x; ++x) {
                if (st[x] == x && slack[x] && st[slack[x]] != x && dist(g[slack[x]][x]) == 0)
                    if (on_found_edge(g[slack[x]][x])) return 1;
            }
            for (int b = n + 1; b <= n_x; ++b) {
                if (st[b] == b && S[b] == 1 && lab[b] == 0) expand_blossom(b);
            }
        }
        return 0;
    }
    pair<ll, int> solve() {
        fill(match, match + n + 1, 0);
        n_x = n;
        int cnt = 0;
        ll ans = 0;
        for (int u = 0; u <= n; ++u) st[u] = u, flower[u].clear();
        ll w_max = 0;
        for (int u = 1; u <= n; ++u) {
            for (int v = 1; v <= n; ++v) {
                flower_from[u][v] = (u == v ? u : 0);
                w_max = max(w_max, g[u][v].w);
            }
        }
        for (int u = 1; u <= n; ++u) lab[u] = w_max;
        while (matching()) ++cnt;
        for (int u = 1; u <= n; ++u) {
            if (match[u] && match[u] < u) ans += g[u][match[u]].w;
        }
        for (int i = 0; i < n; ++i) match[i] = match[i + 1] - 1;
        return make_pair(ans, cnt);
    }
};

Blossom blossom(500);

int main() {
    ios::sync_with_stdio(false);

    int N, M, K;
    cin >> N >> M >> K;

    vector<int> C(K);
    for (int i = 0; i < K; i++) {
        cin >> C[i];
    }
    K += 2;
    C.push_back(0);
    C.push_back(N - 1);

    for (int i = 0; i < M; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        grafo[a].emplace_back(b, c);
        grafo[b].emplace_back(a, c);
    }

    for (int i = 0; i < N; i++) {
        dijkstra(i);
    }

    for (int i = 0; i < K; i++) {
        for (int j = 0; j < K; j++) {
            blossom.add_edge(i, j, dist[C[i]][C[j]]);
        }
    }

    auto sol = blossom.solve();
    assert(2 * sol.second == K);

    cout << sol.first << endl;

    return 0;
}

SubtaskSumTestVerdictTimeMemory
subtask10/0
1Accepted21ms41772 KiB
2Accepted20ms41824 KiB
subtask225/25
3Accepted17ms42088 KiB
4Accepted24ms42876 KiB
5Accepted28ms43852 KiB
6Accepted165ms46992 KiB
7Accepted462ms51276 KiB
8Accepted268ms50888 KiB
9Accepted27ms46776 KiB
subtask335/35
10Accepted21ms43372 KiB
11Accepted24ms44328 KiB
12Accepted32ms45308 KiB
13Accepted167ms48328 KiB
14Accepted419ms51852 KiB
15Accepted257ms51544 KiB
16Accepted27ms47668 KiB
17Accepted284ms51988 KiB
18Accepted298ms52136 KiB
subtask440/40
19Accepted39ms45700 KiB
20Accepted188ms48696 KiB
21Accepted788ms52880 KiB
22Accepted439ms51964 KiB
23Accepted314ms48124 KiB
24Accepted340ms52708 KiB
25Accepted804ms52676 KiB
26Accepted714ms52444 KiB
27Accepted337ms52684 KiB
28Accepted739ms52784 KiB
29Accepted640ms52296 KiB