思路是参考别人而写的!按照别人思路,敲了一遍代码!题意:给出n,p,一共有n个节点,要求最少减去最少的边是多少,剩下p个节点http://blog.csdn.net/libin56842/article/details/9834101 (思路转自别人)思路:典型的树形DP,dp[s][i]:记录s结点,要得到一棵j个节点的子树去掉的最少边数考虑其儿子k1)如果不去掉k子树,则dp[s][i] = min(dp[s][j]+dp[k][i-j]) 0 <= j <= i2)如果去掉k子树,则dp[s][i] = dp[s][i]+1总的为dp[s][i] = min (min(dp[s][j]+dp[k][i-j]) , dp[s][i]+1 )
本人代码:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>using namespace std;int dp[155][155],n,m,num;vector<int>id[155];void dfs(int p,int t){ if(id[p].size()==1&&t!=-1) return ; for(int i=0;i<id[p].size();i++) { int k=id[p][i]; if(k==t) continue; dfs(k,p); for(int j=m;j>=1;j--) { int sum=dp[p][j]+1; for(int tt=1;tt<j;tt++) sum=min(dp[p][tt]+dp[k][j-tt],sum); dp[p][j]=sum; //printf("%d %d %d\n",p,j,dp[p][j]); } }}void solve(int p,int t){ if(id[p].size()==1&&t!=-1) { if(t!=-1) num=min(dp[p][m]+1,num); else num=min(dp[p][m],num); return ; } for(int i=0;i<id[p].size();i++) { int k=id[p][i]; if(k==t) continue; if(t!=-1) num=min(dp[p][m]+1,num); else num=min(dp[p][m],num); solve(k,p); }}int main(){ int i,j,a,b; while(scanf("%d %d",&n,&m)!=EOF) { if(n==1) { printf("0\n"); continue; } for(i=0;i<=n;i++) id[i].clear(); num=99999999; for(i=1;i<n;i++) { scanf("%d %d",&a,&b); id[a].push_back(b); id[b].push_back(a); } for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(j!=1) dp[i][j]=99999999; else dp[i][1]=0; } } dfs(1,-1); solve(1,-1); printf("%d\n",num); } return 0;}
0 0