洛谷P1273 有限电视网题解
本题是树形dp+分组背包问题
根据本题的条件,我们自然可以设计二维dp状态 f[i][j],显然第一维表示的是以i为根节点的树,那么考虑第二维
第二维有两种可能,一种是总价值,一种是总人数,我们可以想到控制价值并不好做,因为价值可以很大,导致数组开不起来,还有就是价值可能为负,所以我们控制第二维是以i为根节点,疏通j人的最大价值,只需要价值大于0,就满足题意。
值得一提的是我们使用了滚动数组优化,其实本来状态应该是三维,我们省略了枚举子节点的维,只需要在枚举人数的时候,倒序枚举即可。
#include<iostream> #include<cstdio> #include<vector> #include<cstring> using namespace std; typedef long long ll; const int N=3010; int f[3010][3010]; int h[N],e[N],ne[N],w[N]; int n,m; int va[N]; int cnt; void add(int a,int b,int c){ e[cnt]=b,w[cnt]=c,ne[cnt]=h[a],h[a]=cnt++; } int dfs(int u){ if(u>n-m){ f[u][1]=va[u]; return 1; } int i,j,k,t; int sum=0; for(i=h[u];i!=-1;i=ne[i]){ int tmp=e[i]; j=dfs(tmp); sum+=j; for(t=sum;t>0;t--){ for(k=1;k<=j;k++){ if(t>=k) f[u][t]=max(f[u][t],f[u][t-k]+f[tmp][k]-w[i]); } } } return sum; } int main(){ cin>>n>>m; memset(h,-1,sizeof h); memset(f,-0x3f,sizeof f); int i; for(i=1;i<=n-m;i++){ int si=0; cin>>si; int j,k; for(j=1;j<=si;j++){ int v; cin>>v>>k; add(i,v,k); } } for(i=n-m+1;i<=n;i++){ cin>>va[i]; } for(i=1;i<=n;i++){ f[i][0]=0; } dfs(1); for(i=m;i>=1;i--){ if(f[1][i]>=0){ cout<<i<<endl; break; } } return 0; }
没有人不辛苦,只有人不喊疼