답안 #726372

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
726372 2023-04-18T19:25:16 Z vjudge1 통행료 (APIO13_toll) C++17
100 / 100
2277 ms 8236 KB
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx,avx2,fma,popcnt")
#include <bits/stdc++.h>
using namespace std;

int n, m, k;
int a[300000], b[300000], c[300000], ord[300000], cnt[300000];
int x[20], y[20], cost[20];
int id[100000];
int pa[40], up[40], depth[40];
int64_t p[100000], pp[100000], sz[100000];
int par[100000];
vector<pair<int, int>> adj[40];

inline int root(int u) { return par[u] < 0 ? u : par[u] = root(par[u]); }

bool unite(int u, int v) {
        u = root(u), v = root(v);
        if (u == v) return 0;
        if (par[u] > par[v]) swap(u, v);
        p[u] += p[v];
        par[u] += par[v];
        par[v] = u;
        return 1;
}
void dfs(const int& u, const int& pr) {
        pa[u] = pr;
        for (pair<int, int>& e : adj[u]) {
                if (e.first == pr) continue;
                up[e.first] = e.second;
                depth[e.first] = depth[u] + 1;
                dfs(e.first, u);
        }
}
int64_t ans = 0;
void dfsans(const int& u, const int& pr) {
        sz[u] = pp[u];
        for (pair<int, int>& e : adj[u]) {
                if (e.first == pr) continue;
                dfsans(e.first, u);
                sz[u] += sz[e.first];
                if (e.second != -1) ans += 1ll * cost[e.second] * sz[e.first];
        }
}
int32_t main() {
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cin >> n >> m >> k;
        for (int i = 0; i < m; i++) cin >> a[i] >> b[i] >> c[i], a[i]--, b[i]--;
        for (int i = 0; i < k; i++) cin >> x[i] >> y[i], x[i]--, y[i]--;
        for (int i = 0; i < n; i++) cin >> pp[i];

        memset(par, -1, n * sizeof *par);
        iota(ord, ord + m, 0);
        sort(ord, ord + m, [&](int a, int b) {
                return c[a] < c[b];
        });
        for (int j = 0; j < m; j++) {
                cnt[ord[j]] += unite(a[ord[j]], b[ord[j]]);
        }  // spanning tree with 0 new edge

        memset(par, -1, n * sizeof *par);
        for (int i = 0; i < k; i++) {
                unite(x[i], y[i]);
        }
        for (int j = 0; j < m; j++) {
                cnt[ord[j]] += unite(a[ord[j]], b[ord[j]]);
        }  // spanning tree with k new edges

        vector<int> almost_mst;
        memset(par, -1, n * sizeof *par);
        for (int i = 0; i < n; i++) p[i] = pp[i];
        for (int i = 0; i < m; i++) {
                if (cnt[ord[i]] == 1) almost_mst.emplace_back(ord[i]);
                if (cnt[ord[i]] == 2) unite(a[ord[i]], b[ord[i]]);
        }

        int N = 0;
        for (int i = 0; i < n; i++) {
                if (root(i) == i) id[i] = N, pp[N++] = p[i];
        }
        for (int j = 0; j < k; j++) x[j] = id[root(x[j])];
        for (int j = 0; j < k; j++) y[j] = id[root(y[j])];
        for (int j : almost_mst) a[j] = id[root(a[j])];
        for (int j : almost_mst) b[j] = id[root(b[j])];

        const int ROOT = id[root(0)];

        int64_t res = 0;

        for (int i = 1; i < 1 << k; i++) {
                memset(par, -1, N * sizeof *par);
                bool ok = 1;
                for (int j = 0; j < k; j++) {
                        if (i >> j & 1) {
                                cost[j] = 1e6;
                                if (!unite(x[j], y[j])) ok = 0;
                        }
                }
                if (!ok) continue;
                vector<int> not_mst;

                for (int j : almost_mst) {
                        if (!unite(a[j], b[j])) {
                                not_mst.emplace_back(j);
                        } else {
                                adj[a[j]].emplace_back(b[j], -1);
                                adj[b[j]].emplace_back(a[j], -1);
                        }
                }

                for (int j = 0; j < k; j++) {
                        if (i >> j & 1) {
                                adj[y[j]].emplace_back(x[j], j);
                                adj[x[j]].emplace_back(y[j], j);
                        }
                }

                ;

                depth[ROOT] = 0;
                dfs(ROOT, -1);

                for (int j : not_mst) {
                        int u = a[j], v = b[j];
                        if (depth[u] < depth[v]) swap(u, v);
                        while (depth[u] > depth[v]) {
                                int id = up[u];
                                if (id != -1) cost[id] = min(cost[id], c[j]);
                                u = pa[u];
                        }
                        while (u != v) {
                                int id;
                                id = up[u];
                                if (id != -1) cost[id] = min(cost[id], c[j]);
                                u = pa[u];
                                id = up[v];
                                if (id != -1) cost[id] = min(cost[id], c[j]);
                                v = pa[v];
                        }
                }

                ans = 0;
                dfsans(ROOT, -1);
                for (int j = 0; j < N; j++) adj[j].clear();
                res = max(res, ans);
        }

        cout << res;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 340 KB Output is correct
2 Correct 0 ms 340 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 340 KB Output is correct
2 Correct 0 ms 340 KB Output is correct
3 Correct 2 ms 340 KB Output is correct
4 Correct 1 ms 340 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 340 KB Output is correct
2 Correct 0 ms 340 KB Output is correct
3 Correct 2 ms 340 KB Output is correct
4 Correct 1 ms 340 KB Output is correct
5 Correct 4 ms 468 KB Output is correct
6 Correct 3 ms 468 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 340 KB Output is correct
2 Correct 0 ms 340 KB Output is correct
3 Correct 2 ms 340 KB Output is correct
4 Correct 1 ms 340 KB Output is correct
5 Correct 4 ms 468 KB Output is correct
6 Correct 3 ms 468 KB Output is correct
7 Correct 195 ms 8200 KB Output is correct
8 Correct 214 ms 8120 KB Output is correct
9 Correct 267 ms 8204 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 340 KB Output is correct
2 Correct 0 ms 340 KB Output is correct
3 Correct 2 ms 340 KB Output is correct
4 Correct 1 ms 340 KB Output is correct
5 Correct 4 ms 468 KB Output is correct
6 Correct 3 ms 468 KB Output is correct
7 Correct 195 ms 8200 KB Output is correct
8 Correct 214 ms 8120 KB Output is correct
9 Correct 267 ms 8204 KB Output is correct
10 Correct 1725 ms 8228 KB Output is correct
11 Correct 2277 ms 8220 KB Output is correct
12 Correct 2272 ms 8236 KB Output is correct