[poj 1947]树dp+背包问题
题目链接:http://poj.org/problem?id=1947
看了很多题解都是直接一遍dfs就搞定的方法,但是我实在是没看懂那个转移方程。最后在茫茫博客中终于发现了一个有逻辑的方法,但是复杂度好像要高一些,但是还是把这个题过了。http://www.chongchonggou.com/g_91242661.html
#include<cstdio> #include<vector> #include<cstring> using namespace std; const int maxn=155; vector<int> G[maxn]; const int INF=0x3f3f3f3f; int dp[2][maxn]; int f[maxn][maxn]; int res[maxn][maxn]; void dfs(int u,int fa) { if (G[u].size()==0) { f[u][0]=f[u][1]=0; if (fa==-1) res[u][0]=res[u][1]=0; else res[u][0]=res[u][1]=1; } else { for (int i=0;i<G[u].size();i++) { int v=G[u][i]; dfs(v,u); } memset(dp,INF,sizeof(dp)); dp[0][0]=0; for (int i=1;i<=G[u].size();i++) { for (int j=0;j<=150;j++) { dp[i&1][j]=INF; for (int k=0;k<=j;k++) { dp[i&1][j]=min(dp[i&1][j],dp[i&1^1][j-k]+f[G[u][i-1]][k]+(k==0)); } } } f[u][0]=0; if (fa==-1) res[u][0]=0; else res[u][0]=1; for (int i=1;i<=150;i++) f[u][i]=dp[G[u].size()&1][i-1]; for (int i=1;i<=150;i++) res[u][i]=f[u][i]+(fa!=-1); } } int main() { memset(f,INF,sizeof(f)); memset(res,INF,sizeof(res)); int n,P; scanf("%d%d",&n,&P); for (int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); } dfs(1,-1); int ans=INF; for (int i=1;i<=n;i++) ans=min(ans,res[i][P]); printf("%d\n",ans); return 0; }