제출 #147020

#제출 시각아이디문제언어결과실행 시간메모리
147020qkxwsm통행료 (APIO13_toll)C++14
0 / 100
41 ms42788 KiB
#include <bits/stdc++.h> using namespace std; template<class T, class U> void ckmin(T &a, U b) { if (a > b) a = b; } template<class T, class U> void ckmax(T &a, U b) { if (a < b) a = b; } #define MP make_pair #define PB push_back #define LB lower_bound #define UB upper_bound #define fi first #define se second #define FOR(i, a, b) for (auto i = (a); i < (b); i++) #define FORD(i, a, b) for (auto i = (a) - 1; i >= (b); i--) #define SZ(x) ((int) ((x).size())) #define ALL(x) (x).begin(), (x).end() #define MAXN 300013 typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; typedef vector<int> vi; typedef vector<ll> vl; typedef vector<pii> vpi; typedef vector<pll> vpl; int N, M, K, T; vector<pair<ll, pii> > edges; vi edge[MAXN], edge1[MAXN]; int ancestor[20][MAXN]; ll arr[MAXN]; int st[MAXN]; vi nodes; map<int, ll> cost[MAXN], weight[MAXN]; vpi cand; int dsu[MAXN]; bitset<MAXN> flag, take, imp; int parent[MAXN], depth[MAXN]; ll dp[MAXN], subtree[MAXN]; pii bound[MAXN]; ll ans; bool cmp(int a, int b) { return st[a] < st[b]; } int get(int u) { return (u == dsu[u] ? u : dsu[u] = get(dsu[u])); } bool merge(int u, int v) { u = get(u); v = get(v); if (u == v) return false; dsu[u] = v; return true; } void dfs1(int u, int p) { st[u] = T; T++; subtree[u] = arr[u]; for (int v : edge[u]) { if (v == p) continue; parent[v] = u; depth[v] = depth[u] + 1; dfs1(v, u); subtree[u] += subtree[v]; } } void dfs(int u, int p) { subtree[u] = weight[u][u]; for (int v : edge1[u]) { if (v == p) continue; parent[v] = u; dfs(v, u); subtree[u] += subtree[v]; subtree[u] += weight[u][v]; } return; } void mark(int u) { //lower, upper if (flag[u]) bound[u].se = u; for (int v : edge[u]) { if (v == parent[u]) continue; bound[v].se = bound[u].se; mark(v); bound[u].fi = bound[v].fi; } if (flag[u]) bound[u].fi = u; } int lca(int u, int v) { if (depth[u] > depth[v]) swap(u, v); FORD(i, 20, 0) { if ((depth[v] - depth[u]) & (1 << i)) v = ancestor[i][v]; } if (u == v) return u; FORD(i, 20, 0) { if (ancestor[i][v] != ancestor[i][u]) { u = ancestor[i][u]; v = ancestor[i][v]; } } return parent[u]; } int32_t main() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> N >> M >> K; flag[0] = true; FOR(i, 0, M) { int u, v; ll d; cin >> u >> v >> d; u--; v--; if (u > v) swap(u, v); edges.PB({d, {u, v}}); } FOR(i, 0, K) { int u, v; cin >> u >> v; u--; v--; cand.PB({u, v}); flag[u] = true; flag[v] = true; } flag[0] = true; FOR(i, 0, N) { cin >> arr[i]; dsu[i] = i; } sort(ALL(edges)); for (auto e : edges) { // cerr << "HI\n"; int u = e.se.fi, v = e.se.se; ll d = e.fi; if (merge(u, v)) { cost[u][v] = d; cost[v][u] = d; edge[u].PB(v); edge[v].PB(u); // cerr << u << ' ' << v << ' ' << cost[u][v] << endl; } } parent[0] = N; dfs1(0, N); FOR(i, 0, 20) ancestor[i][N] = N; FOR(i, 0, N) ancestor[0][i] = parent[i]; FOR(i, 0, 19) { FOR(j, 0, N) { ancestor[i + 1][j] = ancestor[i][ancestor[i][j]]; } } FOR(i, 0, N) if (flag[i]) nodes.PB(i); sort(ALL(nodes), cmp); vi tmp; tmp.PB(0); FOR(i, 1, SZ(nodes)) { int u = nodes[i - 1], v = nodes[i], w = lca(u, v); if (w != u && w != v) tmp.PB(w); tmp.PB(v); } nodes = tmp; for (int u : nodes) flag[u] = true; FOR(i, 0, SZ(nodes) - 1) { int u = nodes[i], v = nodes[i + 1]; if (depth[v] < depth[u]) swap(u, v); ll len = 0, wei = 0; while(v != u) { assert(v != N); wei += arr[v]; ckmax(len, cost[v][parent[v]]); v = parent[v]; } edges.PB({len, {u, v}}); } sort(ALL(edges)); FOR(i, 0, N) bound[i] = {-1, -1}; mark(0); FOR(i, 0, N) if (bound[i].fi == -1) bound[i].fi = bound[i].se; FOR(i, 0, N) { weight[bound[i].fi][bound[i].se] += arr[i]; if (bound[i].fi != bound[i].se) weight[bound[i].se][bound[i].fi] += arr[i]; } parent[0] = N; sort(ALL(nodes)); nodes.erase(unique(ALL(nodes)), nodes.end()); FOR(i, 0, (1 << K)) { // cerr << "SOLVE " << i << endl; for (int x : nodes) { dsu[x] = x; edge1[x].clear(); dp[x] = 0; imp[x] = false; } FOR(j, 0, K) { if (!(i & (1 << j))) continue; int u = cand[j].fi, v = cand[j].se; merge(u, v); } FOR(j, 0, SZ(edges)) { int u = edges[j].se.fi, v = edges[j].se.se; take[j] = merge(u, v); } FOR(j, 0, K) { if (!(i & (1 << j))) continue; int u = cand[j].fi, v = cand[j].se; edge1[u].PB(v); edge1[v].PB(u); // cerr << u << " -> " << v << endl; } FOR(j, 0, SZ(edges)) { if (!take[j]) continue; int u = edges[j].se.fi, v = edges[j].se.se; edge1[u].PB(v); edge1[v].PB(u); // cerr << u << " -> " << v << endl; } dfs(0, N); FOR(j, 0, K) { if (!(i & (1 << j))) continue; int u = cand[j].fi, v = cand[j].se; if (v == parent[u]) swap(u, v); imp[v] = true; } FORD(j, SZ(edges), 0) { if (take[j]) continue; int u = edges[j].se.fi, v = edges[j].se.se; ll d = edges[j].fi; //everything on the path u...v gets capped to vi pu, pv; while(u != 0) { pu.PB(u); u = parent[u]; } while(v != 0) { pv.PB(v); v = parent[v]; } while(!pu.empty() && !pv.empty() && pu.back() == pv.back()) { pu.pop_back(); pv.pop_back(); } for (int x : pu) dp[x] = d; for (int x : pv) dp[x] = d; } ll res = 0; for (int x : nodes) { if (!imp[x]) continue; // cerr << "ADD " << x << endl; res += subtree[x] * dp[x]; } ckmax(ans, res); // cerr << "RES " << res << endl; } cout << ans << '\n'; 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...
#Verdict Execution timeMemoryGrader output
Fetching results...