#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
using ll = long long;
const ll INF = (ll)1e18;
const int MAXN = 10005;
// input
int n, k, root;
// adjacency via edge-list
int head[MAXN], nxt[2*MAXN], to[2*MAXN], wgt[2*MAXN], ec=0;
void addEdge(int u, int v, int w){
nxt[++ec] = head[u];
head[u] = ec;
to[ec] = v;
wgt[ec] = w;
}
// DP:
// f[u][j][0] = best *closed* cost to pick j rooms in u’s subtree, start-and-end at u
// f[u][j][1] = best *open* cost to pick j rooms, start at u, end anywhere
ll f[MAXN][MAXN][2];
// scratch arrays for merging children: curr[state][j], nextdp[state][j]
ll curr[2][MAXN], nextdp[2][MAXN];
int sz[MAXN];
void dfs(int u, int p){
// recurse children first
for(int e = head[u]; e; e = nxt[e]){
int v = to[e];
if(v==p) continue;
dfs(v, u);
}
// ---- FIXED INITIALIZATION ----
// Before merging any child, we have only picked u itself (j=1), cost=0
for(int s0 = 0; s0 < 2; s0++){
for(int j = 0; j <= k; j++){
curr[s0][j] = INF;
}
}
curr[0][1] = 0; // closed, 1 room
curr[1][1] = 0; // open, 1 room
sz[u] = 1;
// -----------------------------
// now merge each child's DP
for(int e = head[u]; e; e = nxt[e]){
int v = to[e], c = wgt[e];
if(v==p) continue;
int su = sz[u], sv = sz[v];
int ns = min(k, su + sv);
// clear nextdp
for(int s0 = 0; s0 < 2; s0++){
for(int j = 0; j <= ns; j++){
nextdp[s0][j] = INF;
}
}
// merge child v
for(int i = 1; i <= su; i++){
ll cu0 = curr[0][i];
ll cu1 = curr[1][i];
if(cu0>=INF && cu1>=INF) continue;
// skip child entirely (j2=0 ⇒ cost 0)
nextdp[0][i] = min(nextdp[0][i], cu0);
nextdp[1][i] = min(nextdp[1][i], cu1);
// take j2=1..sv rooms from child
for(int j2 = 1; j2 <= sv && i+j2 <= k; j2++){
ll cl = f[v][j2][0];
ll op = f[v][j2][1];
if(cl < INF){
ll cost_cl = cl + 2LL*c; // go & return
nextdp[0][i+j2] = min(nextdp[0][i+j2], cu0 + cost_cl);
nextdp[1][i+j2] = min(nextdp[1][i+j2], cu1 + cost_cl);
}
if(op < INF){
ll cost_op = op + 1LL*c; // go but not return
nextdp[1][i+j2] = min(nextdp[1][i+j2], cu0 + cost_op);
}
}
}
// copy back and update size
sz[u] = ns;
for(int s0 = 0; s0 < 2; s0++){
for(int j = 1; j <= sz[u]; j++){
curr[s0][j] = nextdp[s0][j];
}
}
}
// write into f[u]
for(int j = 1; j <= sz[u]; j++){
f[u][j][0] = curr[0][j];
f[u][j][1] = curr[1][j];
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> k >> root;
memset(head, 0, sizeof(head));
// read edges
for(int i = 1; i < n; i++){
int u,v,w;
cin >> u >> v >> w;
addEdge(u,v,w);
addEdge(v,u,w);
}
// initialize f to INF
for(int u = 1; u <= n; u++){
for(int j = 0; j <= k; j++){
f[u][j][0] = f[u][j][1] = INF;
}
}
dfs(root, 0);
// print the *open* tour cost for exactly k rooms
cout << f[root][k][1] << "\n";
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... |