1370 2022. 07. 27 20:37:44 mraron Készülés a Maratonra 2 cpp14 Elfogadva 100/100 804ms 52880 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;
}

Részfeladat Összpont Teszt Verdikt Idő Memória
subtask1 0/0
1 Elfogadva 21ms 41772 KiB
2 Elfogadva 20ms 41824 KiB
subtask2 25/25
3 Elfogadva 17ms 42088 KiB
4 Elfogadva 24ms 42876 KiB
5 Elfogadva 28ms 43852 KiB
6 Elfogadva 165ms 46992 KiB
7 Elfogadva 462ms 51276 KiB
8 Elfogadva 268ms 50888 KiB
9 Elfogadva 27ms 46776 KiB
subtask3 35/35
10 Elfogadva 21ms 43372 KiB
11 Elfogadva 24ms 44328 KiB
12 Elfogadva 32ms 45308 KiB
13 Elfogadva 167ms 48328 KiB
14 Elfogadva 419ms 51852 KiB
15 Elfogadva 257ms 51544 KiB
16 Elfogadva 27ms 47668 KiB
17 Elfogadva 284ms 51988 KiB
18 Elfogadva 298ms 52136 KiB
subtask4 40/40
19 Elfogadva 39ms 45700 KiB
20 Elfogadva 188ms 48696 KiB
21 Elfogadva 788ms 52880 KiB
22 Elfogadva 439ms 51964 KiB
23 Elfogadva 314ms 48124 KiB
24 Elfogadva 340ms 52708 KiB
25 Elfogadva 804ms 52676 KiB
26 Elfogadva 714ms 52444 KiB
27 Elfogadva 337ms 52684 KiB
28 Elfogadva 739ms 52784 KiB
29 Elfogadva 640ms 52296 KiB