Luogu 1273(树形dp)(背包dp)

来源:互联网 发布:网页关键词 的优化 编辑:程序博客网 时间:2024/06/06 00:07

传送门
直接算用户数不好定义状态,于是考虑将收益最大化,收益最大化就能服务更多用户,所以定义dp[p][i]:p点选i个用户的最大收益
然后树形dp即可:
dp[p][i]=max{dp[v][j]+dp[p][i-j]-cost[v]};

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int MAXN=3002,INF=0x3f3f3f3f;int n,m;int head[MAXN],cost[MAXN],val[MAXN],siz[MAXN],edge=0;int dp[MAXN][MAXN];struct EDGE {    int v,nxt;}e[MAXN];inline int read() {    int x=0,f=1;char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();    return x*f;}inline void adde(int u,int v) {    e[edge].nxt=head[u],e[edge].v=v,head[u]=edge++;}void dfs(int p) {    dp[p][0]=0;    for (int ii=head[p];~ii;ii=e[ii].nxt) {        int v=e[ii].v;        dfs(v);        siz[p]+=siz[v];        for (int i=siz[p];i;--i)            for (int j=1;j<=i;++j)                dp[p][i]=max(dp[p][i],dp[v][j]+dp[p][i-j]-cost[v]);    }}int main() {//  freopen("P1273.in","r",stdin);    memset(head,-1,sizeof(head)),    n=read(),m=read();    for (int i=1;i<=n-m;++i) {        int temp=read();        while (temp--) {            int x=read();            cost[x]=read();            adde(i,x);        }    }    for (int i=n-m+1;i<=n;++i) val[i]=read();    memset(siz,0,sizeof(siz));    memset(dp,-INF,sizeof(dp));    for (int i=n-m+1;i<=n;++i) dp[i][1]=val[i],siz[i]=1;    dfs(1);    for (int i=n;i;--i)        if (dp[1][i]>=0) {printf("%d\n",i);break;}    return 0;}
原创粉丝点击