jzoj 5661. 【GDOI2018Day1模拟4.17】药香沁鼻

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq872425710/article/details/79980497

题目大意:

这里写图片描述

思路:

因为选y一定要先选x,所以这是一题0.1分数规划的树形依赖背包。(比较懒)
先用dfs把树转化成序列,如果cnt>W[I]那么就是可以装下的那么当先点的背包就是从他的子节点加上自己价值的背包或者兄弟节点的背包加上自己。如果cnt>W[I]就直接把他和他的兄弟背包合并。最后求出答案就好了。

程序:

#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 5005
using namespace std;
int f[N][N*2],w[N],v[N],last[N],a[N],c[N],t[N];
int n,p,cnt,fa,s,ans;
struct data{int next,to;}e[N*2];
void add(int x,int y){
    e[++cnt].next=last[x]; e[cnt].to=y; last[x]=cnt;
    e[++cnt].next=last[y]; e[cnt].to=x; last[y]=cnt;
} 


void dfs(int x,int fa){
    s++;
    a[x]=1;
    t[s]=x;
    for (int i=last[x];i;i=e[i].next)
    if (fa!=e[i].to)  {
        dfs(e[i].to,x);
        a[x]+=a[e[i].to];
    }
}

void dp(){
    for (int i=n;i;i--){
        int x=t[i];
        for (int j=0;j<=p;j++){
            if (j<w[x]) f[i][j]=f[i+a[x]][j];
            else f[i][j]=max(f[i+1][j-w[x]]+v[x],f[i+a[x]][j]);
        }
    }
}

int main(){
    freopen("medicine.in","r",stdin);
    freopen("medicine.out","w",stdout);
    scanf("%d%d",&n,&p);
    for (int i=1;i<=n;i++){
        scanf("%d%d%d",&w[i],&fa,&v[i]);
        if (i!=1)add(i,fa);
    }
    s=0;
    dfs(1,0);
    dp();
    printf("%d",f[1][p]);
}
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页