[POJ1947] Rebuilding Roads, tree-like DP (this article grouping backpack practices), poj1947rebuilding
Question: Given a tree with n nodes, we need to cut some edges to make the tree with m nodes exist and ask how many edges are cut at least.
Question:
Tree DP is no doubt! And then how to do it.
First, we can think of assigning nodes to Subtrees for a dfs, but oiers who have made tree-like DP know that the distribution method is almost in full arrangement, so they will die, pruning is not active!
Okay, then we have the optimization of the right brother of the Left son, that is, building a new role, classifying the first son as the left child node, and then the rest of the son will be thrown to the right tree of the son in turn, if you don't repeat it, you can check it by yourself, because this is not the case in this article (it's so disgusting to be tempted, and the code is too complicated !)
Here I will introduce the practices of grouping backpacks (which can solve the problem of more than half of the Left son and right brother of the tree-like DP ).
Practices for grouping backpacks:
That is, each subnode makes a group backpack for its parent node and transfers various statuses! It may be a little bit difficult to handle, but it is still easier to write than the right brother of the Left son! Of course, the status may be a little difficult to think about (or always think wrong, but you have to change it after writing ).
Directly paste the code, which is easier to see (if can be written in the upper and lower bounds when k is enumerated in dfs, it may look more comfortable)
#include <cstdio>#include <cstring>#include <algorithm>#define N 500#define inf 0x3f3f3f3fusing namespace std;struct Syndra{int v,next;}e[N];int head[N],d[N],cnt,n,m,root;void add(int u,int v){++cnt;e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt;d[v]++;}int f[N][N],num[N],ans=inf;void dfs(int x){int i,j,k,v,temp;for(i=head[x];i;i=e[i].next){v=e[i].v;dfs(v);for(j=num[x]+num[v];j;j--){int uplimit=min(j,num[v]);for(k=max(1,j-num[x]);k<=uplimit;k++){f[x][j]=min(f[x][j],f[x][j-k]+f[v][k]);}}num[x]+=num[v];}f[x][++num[x]]=1;}int main(){//freopen("test.in","r",stdin);int i,j,k;int a,b,c;scanf("%d%d",&n,&m);for(i=1;i<n;i++){scanf("%d%d",&a,&b);add(a,b);}memset(f,0x3f,sizeof(f));for(i=1;i<=n;i++){f[i][0]=0;if(!d[i])root=i;}dfs(root);for(i=1;i<=n;i++){f[i][num[i]]=0;ans=min(ans,f[i][num[i]-m]+1);if(i!=root)f[i][n-m]++;ans=min(ans,f[i][n-m]);}printf("%d\n",ans);return 0;}
Copy the Translation results to Google