洛谷 P2014 选课

来源:互联网 发布:软件开发运维驻场合同 编辑:程序博客网 时间:2024/05/29 17:02

传送门
很久以前就写了,然而一直没发博客,现在讲课的时候老师课件里有,我就发上来,这个题还是很好的。
加一个根,将所有树的根都连过去,然后多叉转二叉,树形dp即可。
代码:

#include<bits/stdc++.h>#define ll long longusing namespace std;int n,m;int v[301];int fa[301];int ls[301];int rs[301];vector<int> son[301];void build(int x){    if(son[x].size()==0){        return;    }    int i=0;    ls[x]=son[x][i];    int now=ls[x];    for(i=1;i<son[x].size();i++){        rs[now]=son[x][i];        now=son[x][i];    }    for(int i=0;i<son[x].size();i++){        build(son[x][i]);    }}int f[301][302];int dp(int x,int t){    if(t<=0){        return 0;    }    if(f[x][t]!=0){        return f[x][t];    }    if(ls[x]==0&&rs[x]==0){        f[x][t]=v[x];        return v[x];    }    if(ls[x]==0){        f[x][t]=max(dp(rs[x],t),dp(rs[x],t-1)+v[x]);        return f[x][t];    }    if(rs[x]==0){        f[x][t]=dp(ls[x],t-1)+v[x];        return f[x][t];    }    for(int i=0;i<=t-1;i++){        f[x][t]=max(f[x][t],dp(ls[x],i)+dp(rs[x],t-1-i)+v[x]);    }    f[x][t]=max(f[x][t],dp(rs[x],t));    return f[x][t];}int main(){    scanf("%d %d",&n,&m);    for(int i=1;i<=n;i++){        scanf("%d %d",&fa[i],&v[i]);        son[fa[i]].push_back(i);    }    build(0);    dp(0,m+1);    printf("%d\n",f[0][m+1]);    return 0;}
原创粉丝点击