第三篇:P1272
题解补完计划:第三篇
显然,题目是一棵树,考虑 DP,令 \(dp_{i, j}\) 表示在子树 \(i\) 内,留下 \(j\) 大小的且包含 \(i\) 的联通块的最小代价。
转移有:
\(ndp_{u, i+j} = min_{i=1}^{sz_u} min_{i=1}^{sz_v} dp_{u, i} + dp_{v, j}\)。
表示同时包含 \(u, v\) 的情况下的最小代价。
\(ndp_{u, i} = min(ndp_{u,i}, dp_{u, i}+1)\)。
表示不包含 \(v\) 时的最小代价。
代码:
#include<bits/stdc++.h>
using namespace std;
#define N 205
#define intl long long
#define inf (0x3f3f3f3f3f3f3f3f)
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
intl x=0,k=1;char ch=getchar();
while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*k;
}
intl dp[N][N], sz[N], n, p, tmp[N];
vector<intl> g[N];
void dfs(intl u) {
sz[u] = 1;dp[u][1] = 0;
for(auto v:g[u]) {
dfs(v);
For(i,0,sz[u] + sz[v]) tmp[i] = inf;
For(i,1,sz[u]) For(j,1,sz[v]) tmp[i+j] = min(tmp[i+j], dp[u][i] + dp[v][j]);
For(i,0,sz[u]) tmp[i] = min(tmp[i], dp[u][i] + 1);
sz[u] += sz[v];
For(i,0,sz[u]) dp[u][i] = tmp[i];
}
dp[u][sz[u]] = 0;
}
int main() {
n = read(), p = read();
For(i,2,n) {
intl u = read(), v = read();
g[u].push_back(v);
}
For(i,0,n) For(j,0,n) dp[i][j] = inf;
dfs(1);
intl ans = inf;
For(i,1,n) {
if(dp[i][p] == inf) continue;
ans = min(ans, dp[i][p] + (i != 1));
}
printf("%lld\n", ans);
return 0;
}

浙公网安备 33010602011771号