Rebuilding Roads POJ - 1947
Last Edited: May 27, 2019 7:32 PM
Tags: dynamic programming,poj
设定dp[u][j]为以u为根大小为j的最小值
- 注意dp[u][1] 为1
- 对于每个节点若考虑去除某个子节点显然其已知的dp[u][j]应加一
- 对于保留某子节点的情况需考虑当前为j的情况以及其子节点取k个的情况易得递推式dp[u][j]=dp[u][j-k]+dp[v][k],所以可以得到其必然有子节点至少取一个(不取情况为见2)
#include<cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define fst first
#define sec second
#define sci(num) scanf("%d",&num)
#define scl(num) scanf("%lld",&num)
#define mem(a,b) memset(a,b,sizeof a)
#define cpy(a,b) memcopy(a,b,sizeof b)
#define lc (rt<<1)
#define rc (rt<<1|1)
typedef long long LL;
typedef pair<int,int> P;
const int MAX_N = 200;
const int MOD = 1e9 + 7;
int N,M;
int dp[MAX_N][MAX_N];
vector<int> G[MAX_N];
int fa[MAX_N];
void dfs(int u) {
dp[u][1] = 0;
for (int i = 0;i < G[u].size();i++) {
int v = G[u][i];
dfs(v);
for (int j = M;j >= 1;j--) {
dp[u][j]++;
for (int k = 1;k < j;k++) {
dp[u][j] = min(dp[u][j],dp[v][k]+dp[u][j - k]);
}
}
}
}
int main() {
while (~scanf("%d%d",&N,&M)) {
mem(fa,-1);
mem(dp,0x3f3f3f3f);
for (int i = 0;i <= N;i++)
G[i].clear();
for (int i = 1;i < N;i++) {
int u,v;
sci(u); sci(v);
G[u].push_back(v);
fa[v] = u;
}
int ans;
for (int i = 1;i <= N;i++) {
if (fa[i] != -1) continue;
dfs(i);
ans = dp[i][M];
break;
}
for (int i = 1;i <= N;i++) {
ans = min(ans,dp[i][M]+1);
}
printf("%d\n",ans);
}
}