标签:树形dp
/*#include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<iostream> using namespace std; #define maxn 6005 int dp[maxn][maxn],num[maxn],val[maxn]; vector<int>sons[maxn]; //num对于优化起了很大的作用,来记录当前结点子树中的叶子结点数目 void dfs(int rt){ dp[rt][0]=0; for(int u=0;u<sons[rt].size();u++){ int s=sons[rt][u]; dfs(s); num[rt]+=num[s]; for(int i=num[rt]-num[s]+1;i<=num[rt];i++) dp[rt][i]=-1000000; //要初始化为一个很大的负数 for(int i=num[rt];i>=1;i--){ for(int j=1;j<=num[s]&&j<=i;j++){ dp[rt][i]=max(dp[rt][i],dp[s][j]+dp[rt][i-j]+val[s]); } } } } void init(){ for(int i=0;i<maxn;i++) sons[i].clear(); memset(val,0,sizeof(val)); memset(num,0,sizeof(num)); } void print(){ for(int i=num[1];i>=0;i--) if(dp[1][i]>=0) {printf("%d\n",i);break;} } int main(){ int i,j,n,m,k,a,b; while(~scanf("%d%d",&n,&m)){ init(); for(i=1;i<=n-m;i++){ scanf("%d",&k); for(j=1;j<=k;j++){ scanf("%d%d",&a,&b); sons[i].push_back(a); val[a]=-b; } } for(i=n+1;i<=n+m;i++){ //给每一个叶子结点加一个结点,用它来表示赚的钱,而其它点都表示需要支付的钱 scanf("%d",&val[i]); num[i]=1; sons[i-m].push_back(i); } dfs(1); print(); } return 0; }
标签:树形dp
原文地址:http://blog.csdn.net/crazy__c/article/details/44894439