Submission #442616

#TimeUsernameProblemLanguageResultExecution timeMemory
442616Haruto810198Road Closures (APIO21_roads)C++17
7 / 100
339 ms71344 KiB
#include <bits/stdc++.h> using namespace std; #define int long long #define double long double #define FOR(i,l,r,d) for(int i=(l);i<=(r);i+=(d)) #define szof(x) ((int)(x).size()) #define vi vector<int> #define pii pair<int,int> #define F first #define S second #define pb push_back #define eb emplace_back #define mkp make_pair #define lsb(x) ((x)&(-(x)) const int INF = 2147483647; const int LNF = 4e18; const int MOD = 1000000007; const int mod = 998244353; const double eps = 1e-12; //#pragma GCC optimize("Ofast") //#pragma GCC optimize("unroll-loops") const int MAX = 100010; int n; vector<pii> edge[MAX]; /// original tree int deg[MAX]; /// degree of vertices pii par[MAX]; /// parent and childs of vectices, on the original tree vector<pii> ch[MAX]; vi induced[MAX]; /// vectices of each induced subgraph pii par_induced[MAX]; /// parent and childs of vectices, on the induced subgraph vector<pii> ch_induced[MAX]; int dep[MAX]; /// depth of vectices vi ord; /// order of dp int dp[MAX][2]; /// dp[vertex][is connnected to parent] /// Treap struct Treap{ Treap *l, *r; int key, pri; int sz, sum; Treap(int _k): l(nullptr), r(nullptr), key(_k), pri(rand()), sz(1), sum(_k) {} }; inline int get_sz(Treap *T){ return (T != nullptr) ? T -> sz : 0; } inline int get_sum(Treap *T){ return (T != nullptr) ? T -> sum : 0; } void pull(Treap *&T){ if(T == nullptr) return; T -> sz = get_sz(T -> l) + get_sz(T -> r) + 1; T -> sum = get_sum(T -> l) + get_sum(T -> r) + T -> key; } Treap* Merge(Treap *a, Treap *b){ if(a == nullptr) return b; if(b == nullptr) return a; if(a -> pri < b -> pri){ a -> r = Merge(a -> r, b); pull(a); return a; } else{ b -> l = Merge(a, b -> l); pull(b); return b; } } void Split_by_key(Treap *T, Treap *&a, Treap *&b, int k){ if(T == nullptr){ a = b = nullptr; return; } if(T -> key < k){ a = T; Split_by_key(T->r, a->r, b, k); pull(a); } else{ b = T; Split_by_key(T->l, a, b->l, k); pull(b); } } void Split_by_sz(Treap *T, Treap *&a, Treap *&b, int k){ if(T == nullptr){ a = b = nullptr; return; } if(get_sz(T -> l) + 1 <= k){ a = T; Split_by_sz(T->r, a->r, b, k - get_sz(T -> l) - 1); pull(a); } else{ b = T; Split_by_sz(T->l, a, b->l, k); pull(b); } } void Insert(Treap *&T, int val){ Treap *a, *b; Split_by_key(T, a, b, val); T = Merge( Merge(a, new Treap(val)), b ); } void Erase(Treap *&T, int val){ Treap *a, *b, *c; Split_by_key(T, a, b, val); Split_by_sz(b, b, c, 1); T = Merge(a, c); } Treap* edge_cnt[MAX]; void edge_cnt_insert(int v, int val){ Insert(edge_cnt[v], val); } void edge_cnt_erase(int v, int val){ Erase(edge_cnt[v], val); } int edge_cnt_query(int v, int q){ if(q > get_sz(edge_cnt[v])) return LNF; Treap *a, *b; Split_by_sz(edge_cnt[v], a, b, q); return get_sum(a); } /// calculate dep[], par[], ch[] void dfs(int v, pii pv, int cdep){ par[v] = pv; dep[v] = cdep; for(pii e : edge[v]){ int i = e.F; int w = e.S; if(i == pv.F) continue; ch[v].pb(e); dfs(i, mkp(v, w), cdep + 1); } } bool cmp_by_dep(int u, int v){ return (dep[u] < dep[v]); } /// solve for induced subgraph k int solve(int k){ //cerr<<"solve("<<k<<") : "<<endl; for(int v : induced[k]){ par_induced[v] = mkp(v, 0); ch_induced[v].clear(); } /// update edges in induced subgraph k for(int v : induced[k]){ int u = par[v].F; int w = par[v].S; if(v!=u and deg[u]>k){ par_induced[v] = mkp(u, w); ch_induced[u].eb(v, w); edge_cnt_erase(v, w); edge_cnt_erase(u, w); } } /// dp order ord = induced[k]; sort(ord.begin(), ord.end(), cmp_by_dep); reverse(ord.begin(), ord.end()); /// dp int ret = 0; for(int v : ord){ int ori_cost = 0; /// original cost if don't pick any child int n_sum = 0, n_cnt = 0; /// sum, n. of negative cost child /// cost of picking each child vi cost_ch; for(pii e : ch_induced[v]){ int i = e.F; int w = e.S; /// pick : dp[i][1] + w /// not pick : dp[i][0] cost_ch.pb(dp[i][1] + w - dp[i][0]); ori_cost += dp[i][0]; } sort(cost_ch.begin(), cost_ch.end()); for(int i : cost_ch){ if(i >= 0) break; n_sum += i; n_cnt++; } /// dp[v][0] dp[v][0] = LNF; int pick = deg[v] - k; /// n. of edges must pick to close int cost_ch_sum = n_sum; FOR(pick_ch, 0, pick, 1){ /// n. of edges picked from child int pick_ext = pick - pick_ch; /// n. of edges picked from extra edges dp[v][0] = min(dp[v][0], ori_cost + cost_ch_sum + edge_cnt_query(v, pick_ext)); if(pick_ch >= szof(cost_ch)) break; if(pick_ch >= n_cnt){ cost_ch_sum += cost_ch[pick_ch]; } } /// if v is a root in the induced graph : if(par_induced[v].F == v){ ret += dp[v][0]; continue; } /// dp[v][1] dp[v][1] = LNF; pick = deg[v] - k - 1; cost_ch_sum = n_sum; FOR(pick_ch, 0, pick, 1){ /// n. of edges picked from child int pick_ext = pick - pick_ch; /// n. of edges picked from extra edges dp[v][1] = min(dp[v][1], ori_cost + cost_ch_sum + edge_cnt_query(v, pick_ext)); if(pick_ch >= szof(cost_ch)) break; if(pick_ch >= n_cnt){ cost_ch_sum += cost_ch[pick_ch]; } } } /// recover edge_cnt for(int v : induced[k]){ int u = par[v].F; int w = par[v].S; if(v!=u and deg[u]>k){ edge_cnt_insert(v, w); edge_cnt_insert(u, w); } } /* cerr<<"dp : "<<endl; for(int v : induced[k]){ cerr<<"dp["<<v<<"][0] = "<<dp[v][0]<<"\t dp["<<v<<"][1] = "<<dp[v][1]<<endl; } cerr<<endl; */ return ret; } vi minimum_closure_costs(signed N, vector<signed> U, vector<signed> V, vector<signed> W){ int wsum = 0; /// input n = N; FOR(i, 0, n-2, 1){ int u = U[i], v = V[i], w = W[i]; edge[u].eb(v, w); edge[v].eb(u, w); deg[u]++; deg[v]++; edge_cnt_insert(u, w); edge_cnt_insert(v, w); wsum += w; } /// dfs dfs(0, mkp(0, 0), 0); /// induced subgraph FOR(i, 0, n-1, 1){ FOR(j, 0, deg[i]-1, 1){ induced[j].pb(i); } } /// solve for each induced subgraph vi res(n); res[0] = wsum; FOR(i, 1, n-1, 1){ res[i] = solve(i); } return res; } /* signed main(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); vi res = minimum_closure_costs(4, {0, 2, 0}, {1, 0, 3}, {5, 10, 5}); //vi res = minimum_closure_costs(5, {0, 0, 0, 2}, {1, 2, 3, 4}, {1, 4, 3, 2}); //vi res = minimum_closure_costs(6, {0, 1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 10, 1, 10, 1}); cerr<<"res : "; for(int i : res){ cerr<<i<<" "; } cerr<<endl; 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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...