题意说给你一棵树,问得到点数为p的子树至少要删除多少条边。
状态方程:
好好理解下状态方程。
u的子树v
1、不删除v dp[u][i] = min { dp[u][j] + dp[v][i-j] };
2、删除v(只要删一条边)dp[u][i] = dp[u][i] + 1;
综上:dp[u][i] = min { dp[u][j] +dp[v][i-j] , dp[u][i] + 1 };
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned ui;
const int oo = 0x3f3f3f3f;
//const ll OO = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
#define lson rt<<1
#define rson rt<<1|1
void cmax(int& a, int b){ if (b > a)a = b; }
void cmin(int& a, int b){ if (b < a)a = b; }
void cmax(ll& a, ll b){ if (b > a)a = b; }
void cmin(ll& a, ll b){ if (b < a)a = b; }
void cmax(double& a, double b){ if (a - b < eps) a = b; }
void cmin(double& a, double b){ if (b - a < eps) a = b; }
void add(int& a, int b, int mod){ a = (a + b) % mod; }
void add(ll& a, ll b, ll mod){ a = (a + b) % mod; }
const ll MOD = 1000000007;
const int maxn = 200;
int dp[maxn][maxn];
int father[maxn];
int n, p;
vector<int> G[maxn];
void tree_dp(int u)
{
for (int i = 0; i <= p; i++)
dp[u][i] = oo;
dp[u][1] = 0;
int f = 0;
for (int k = 0; k < G[u].size(); k++)
{
int v = G[u][k];
tree_dp(v);
f = 1;
for (int i = p; i >= 1; i--)
{
dp[u][i] = dp[u][i] + 1;
for (int j = 1; j < i; j++)
dp[u][i] = min(dp[u][i], dp[u][j] + dp[v][i - j]);
}
}
}
int Dp(int root)
{
tree_dp(root);
int ans = dp[root][p];
for (int i = 1; i <= n; i++)
ans = min(dp[i][p] + 1, ans);
return ans;
}
int main()
{
int root, u, v;
while (scanf("%d %d", &n, &p) != EOF)
{
for (int i = 0; i <= n; i++)
G[i].clear();
memset(father, -1, sizeof father);
for (int i = 1; i <= n - 1; i++)
{
scanf("%d %d", &u, &v);
G[u].push_back(v);
father[v] = u;
}
for (int i = 1; i <= n; i++)
if (father[i] == -1)
{
root = i;
break;
}
printf("%d\n", Dp(root));
}
return 0;
}