[vijos 1642]班长的任务 [树形dp]

背景

十八居士的毕业典礼(1)

描述

福州时代中学2009届十班同学毕业了,于是班长PRT开始筹办毕业晚会,但是由于条件有限,可能每个同学不能都去,但每个人都有一个权值,PRT希望来的同学们的权值总和最大。

十班有一个周密的电话通知网络,它其实就是一棵树,根结点为班长PRT,由她来负责通知她的下线(也就是儿子节点),下线们继续通知自己的下线(不一定每个下线都要通知),任何人都可以不去:”
为了使权值总和最大,班长想安排一下人,但是人数很多,人脑是难以应付的,所以她找到十八居士,让他编程用电脑解决。

格式

输入格式

输入第一行两个整数n,m表示有n位同学,至多只能去m位同学。(1<=m<=n)
接下来2*n行,每两行代表一个同学的信息(如果这位同学没有子节点,就只有一行)。

每个同学的第一行两个整数p,s,表示这位同学权值为p,子节点个数s;(-100<=p<=100)
第二行s个整数,表示这位同学的子节点的编号。

班长的编号一定为1。

对于20%数据1<=n<=10
对于60%数据1<=n<=100
对于100%数据1<=n<=1000

输出格式

输出一个整数,表示权值的最大值。

样例

样例输入1

8 5
100 2
2 3
79 2
4 5
109 3
6 7 8
100 0
100 0
100 0
101 0
108 0

样例输出1

518


My Solution

id序列树形dp!!!

神秘!

const int maxn=1001;
int d[maxn];               -------->WA!!!!

int d[1001];                -------->AC!!!!

于是我改成了

const int maxn=1010;
int d[maxn];

AC!!!

C++基本的东西还要多学

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<vector>
 5 using namespace std;
 6 #define inf 0x3f3f3f3f
 7 
 8 inline int read(){
 9     int re=0;
10     char ch;
11     bool flag=0;
12     while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
13     ch=='-'?flag=1:re=ch-'0';
14     while((ch=getchar())>='0'&&ch<='9')  re=(re<<1)+(re<<3)+ch-'0';
15     return flag?-re:re;
16 }
17 
18 struct edge{
19     int to,next;
20     edge(int to=0,int next=0):
21         to(to),next(next){}
22 };
23 
24 const int maxn=1010;
25 
26 vector<edge> edges;
27 int n,m;
28 int head[maxn];
29 int w[maxn],num[maxn];
30 int dp[maxn][maxn];
31 int id[maxn],count[maxn],q=0;
32 int root=1;
33 int cnt=0;
34 int ans=-inf;
35 
36 inline void add_edge(int from,int to){
37     edges.push_back(edge(to,head[from]));
38     head[from]=++cnt;
39 }
40 
41 void init(){
42     n=read();  m=read();
43     edges.push_back(edge(0,0));
44     for(int i=1;i<=n;i++){
45         w[i]=read();
46         num[i]=read();
47         for(int j=1;j<=num[i];j++){
48             int to=read();
49             add_edge(i,to);
50         }
51     }
52 }
53 
54 void dfs(int x){
55     id[++q]=x;
56     count[x]=1;
57     for(int ee=head[x];ee;ee=edges[ee].next){
58         dfs(edges[ee].to);
59         count[x]+=count[edges[ee].to];
60     }
61 }
62 
63 void solve(){
64     memset(dp,-127,sizeof dp);
65     dfs(root);
66     for(int i=1;i<=n;i++){
67         dp[i][0]=0;
68         dp[i][1]=w[id[i]];
69     }
70     for(int i=n-1;i>0;i--)
71         for(int j=1;j<=m;j++)
72             dp[i][j]=max(dp[i+1][j-1]+w[id[i]],dp[i+count[id[i]]][j]);
73     for(int i=1;i<=m;i++)
74         ans=max(ans,dp[1][i]);
75     printf("%d\n",max(ans,0));
76 }
77 
78 int main(){
79     //freopen("temp.in","r",stdin);
80     init();
81     solve();
82     return 0;
83 }

 


 于是他走了  就像他没有来过一样

 

转载于:https://www.cnblogs.com/ZYBGMZL/p/6882676.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值