This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |