이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#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]
int edge_cnt[MAX][11];
void edge_cnt_modify(int v, int pos, int val){
edge_cnt[v][pos] += val;
}
int edge_cnt_query(int v, int q){
int ret = 0;
FOR(i, 1, 10, 1){
ret += i * min(q, edge_cnt[v][i]);
q = max((int)0, q - edge_cnt[v][i]);
}
if(q > 0) return LNF;
return ret;
}
/// 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){
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_modify(v, w, -1);
edge_cnt_modify(u, w, -1);
}
}
/// dp order
ord = induced[k];
sort(ord.begin(), ord.end(), cmp_by_dep);
reverse(ord.begin(), ord.end());
/*
cerr<<"solve("<<k<<") : ";
for(int v : ord){
cerr<<v<<" ";
}
cerr<<endl;
*/
/// dp
int ret = 0;
for(int v : ord){
//cerr<<"dp["<<v<<"] : "<<endl;
int ori_cost = 0; /// original cost if don't pick any 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());
/*
cerr<<"cost_ch : ";
for(int i : cost_ch){
cerr<<i<<" ";
}
cerr<<endl;
*/
/// dp[v][0]
dp[v][0] = ori_cost + LNF;
int pick = deg[v] - k; /// n. of edges must pick to close
int cost_ch_sum = 0;
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] = ori_cost + min(dp[v][0], cost_ch_sum + edge_cnt_query(v, pick_ext));
if(pick_ch >= szof(cost_ch)) break;
cost_ch_sum += cost_ch[pick_ch];
}
assert(dp[v][0] >= 0);
/// 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] = ori_cost + LNF;
pick = deg[v] - k - 1;
cost_ch_sum = 0;
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] = ori_cost + min(dp[v][1], cost_ch_sum + edge_cnt_query(v, pick_ext));
if(pick_ch >= szof(cost_ch)) break;
cost_ch_sum += cost_ch[pick_ch];
}
assert(dp[v][1] >= 0);
}
/// 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_modify(v, w, 1);
edge_cnt_modify(u, w, 1);
}
}
/*
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_modify(u, w, 1);
edge_cnt_modify(v, w, 1);
wsum += w;
}
/// dfs
dfs(0, mkp(0, 0), 0);
/*
cerr<<"par : "<<endl;
FOR(i, 0, n-1, 1){
cerr<<"par["<<i<<"] = ("<<par[i].F<<", "<<par[i].S<<")"<<endl;
}
cerr<<endl;
cerr<<"ch : "<<endl;
FOR(i, 0, n-1, 1){
cerr<<"ch["<<i<<"] = ";
for(pii e : ch[i]){
cerr<<"("<<e.F<<", "<<e.S<<") ";
}
cerr<<endl;
}
cerr<<endl;
cerr<<"dep : "<<endl;
FOR(i, 0, n-1, 1){
cerr<<"dep["<<i<<"] = "<<dep[i]<<endl;
}
cerr<<endl;
*/
/// 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});
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... |