首页 > 代码库 > 洛谷 P1273 有线电视网(dp)
洛谷 P1273 有线电视网(dp)
/*想了半天没想出状态 自己还是太弱了 QAQ题目问的是最多供给多少户 一般想法是把这个值定义为状态量没想出来QAQ....看了看题解的状态 很机智.... f[i][j]表示i的子树 选了j个叶子的最大收益这样 不亏本就是收益>=0 转移的话 先搜一下这个子树有几个叶子 然后枚举儿子 枚举当前儿子分几个叶子 这里的枚举顺序有套路从大到小枚举i分几个 从小到大枚举j分几个这样可以避免 重复选择 注意初始化 */#include<iostream>#include<cstdio>#include<cstring>#define maxn 3010using namespace std;int n,m,p,head[maxn],num,f[maxn][maxn],ans,c[maxn];struct node{ int v,t,pre;}e[maxn];void Add(int from,int to,int dis){ num++;e[num].v=to; e[num].t=dis; e[num].pre=head[from]; head[from]=num; }int Dfs(int u){ if(u>p){ f[u][1]=c[u]; return 1; } int s=0; for(int i=head[u];i;i=e[i].pre){ int v=e[i].v; int x=Dfs(v);s+=x; for(int j=s;j>=1;j--) for(int k=1;k<=x;k++) f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]-e[i].t); } return s;}int main(){ scanf("%d%d",&n,&m);p=n-m; for(int i=1;i<=p;i++){ int x,y,z; scanf("%d",&x); for(int j=1;j<=x;j++){ scanf("%d%d",&y,&z); Add(i,y,z); } } for(int i=p+1;i<=n;i++) scanf("%d",&c[i]); memset(f,-127/3,sizeof(f)); for(int i=1;i<=n;i++) f[i][0]=0; Dfs(1); for(int i=0;i<=m;i++) if(f[1][i]>=0)ans=max(ans,i); printf("%d\n",ans); return 0;}
洛谷 P1273 有线电视网(dp)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。