树形DP pku1947
来源:互联网 发布:淘宝有电脑版客户端吗 编辑:程序博客网 时间:2024/06/03 18:10
其实不管什么DP,本质思想都是不变的,围绕着最优子结构展开思路,最终记录下最优的结果,所以写好状态转移,处理好边界问题,还是关键手段。
状态:dp[i][j]表示以i为根的子树孤立出 j 个点要去掉的最少的边,
在树上的动态规划一般都是父结点和子节点的关系,所以在思考状态转移时时应该尽量把父结点的子节点考虑进去
分别以不同的点为根进行深搜
先要想到我们最后要得到的结果应该是dp[i][p]中的最小值
而dp[i][j]是从dp[u][k]和dp[i][j-k]推过来的,u为i的子节点
还有就是以i为根和以i的子节点为u根时,dp[u][k]+dp[i][j-k]多加了两次他们之间的边,所以要减去2
即dp[root][p]=min(dp[root][p], dp[u][k]+dp[root][p-k]-2);(其中u为root的一个孩子)
View Code
#include<stdio.h>
#include<string.h>
#define N 160
int min(int a,int b)
{
return a<b?a:b;
}
struct node{
int to,next;
}edge[2*N];
int tot=0,n,p;
int head[N],ans[N],dp[N][N];
void add(int a,int b)
{
edge[tot].to=b;
edge[tot].next=head[a];
head[a]=tot++;
}
void DP(int root,int fa)
{
int i,j,k,u;
for(i=head[root];i!=-1;i=edge[i].next)
{
u=edge[i].to;
if(fa!=u) DP(u,root);
}
for(i=head[root];i!=-1;i=edge[i].next)
{
u=edge[i].to;
if(u==fa) continue;
for(j=p;j>=1;j--)
{
for(k=1;k<j;k++)
dp[root][j]=min(dp[root][j],dp[u][k]+dp[root][j-k]-2);
}
}
}
int main()
{
int x,y,i,j;
while(scanf("%d%d",&n,&p)!=EOF)
{
memset(head,-1,sizeof(head));
memset(ans,0,sizeof(ans));
for(i=0;i<n-1;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
ans[x]++;
ans[y]++;
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
dp[i][j]=N;
}
}
for(i=1;i<=n;i++)
dp[i][1]=ans[i];
DP(1,0);
int mi=N;
for(i=1;i<=n;i++)
mi=min(mi,dp[i][p]);
printf("%d\n",mi);
}
return 0;
}
- 树形DP pku1947
- 树形dp
- 树形DP
- 树形dp
- 树形DP
- 树形dp
- 树形DP
- 树形DP
- 树形DP
- 树形DP
- 树形dp
- 树形dp
- 树形dp
- 树形dp
- 树形DP
- 树形DP
- 树形DP
- 树形DP
- pku 1061
- poj pku2263floyd
- 约束的个数
- 用来练习邻接表结构 poj3268 pku spfa
- pku 3660
- 树形DP pku1947
- tubao pku1113
- poj 2481 cows 树状数组 老少皆宜版解答
- hdu 4000 树状数组
- hdu 4006 求第k大的数
- hdu 4046 树状数组
- hdu 3694 费马点的应用
- 一个人的旅行
- poj 2662 A Walk Through the Forest