Description
K妹的胡椒粉大卖,这辣味让食客们感到刺激,许多餐馆也买这位K妹的账。有N家餐馆,有N-1条道路,这N家餐馆能相互到达。K妹从1号餐馆开始。每一个单位时间,K妹可以在所在餐馆卖完尽量多的胡椒粉,或者移动到有道路直接相连的隔壁餐馆。第i家餐馆最多需要A[i]瓶胡椒粉。K妹有M个单位的时间,问她最多能卖多少胡椒粉。
Input
第一行有两个正整数N,M。
第二行描述餐馆对胡椒粉的最大需求量,有N个正整数,表示A[i]。
接下来有N-1行描述道路的情况,每行两个正整数u,v,描述这条道路连接的两个餐馆。
第二行描述餐馆对胡椒粉的最大需求量,有N个正整数,表示A[i]。
接下来有N-1行描述道路的情况,每行两个正整数u,v,描述这条道路连接的两个餐馆。
Output
一个整数,表示她最多能卖的胡椒粉瓶数。
Sample Input
样例1输入 3 5 9 2 5 1 2 1 3 样例2输入 4 5 1 1 1 2 1 2 2 3 3 4 样例3输入 5 10 1 3 5 2 4 5 2 3 1 2 3 4 2
Sample Output
样例1输出 14 样例2输出 3 样例3输出 15
Data Constraint
对于10%的数据,N≤20。
对于50%的数据,N≤110。
对于100%的数据1 ≤ N, M ≤ 500,1 ≤ A[i]≤ 10^6,
第5到第10个测试点都有多个子测试。
对于50%的数据,N≤110。
对于100%的数据1 ≤ N, M ≤ 500,1 ≤ A[i]≤ 10^6,
第5到第10个测试点都有多个子测试。
Hint
在样例1的中,辣妹到达城市2后就恰好没时间卖辣椒粉了。
题解
- 设f[i][j][0/1]为以i为根的子树中 花费j的时间 是否走回根的最大收益(0为有,1为无)
- 枚举下一棵子树时,可以枚举下一棵子树中所用的时间,和当前子树中用的时间
- 考虑三种转移:
- ①之前走过的子树回根 再走到另一棵子树不回根
- f[i][j][1]=f[i][j-k-1][0]+f[son][k][1]
- ②之前走过的子树回根 再走到另一棵子树也回根
- f[i][j][0]=f[i][j-k-2][0]+f[son][k][0]
- ③走到另一棵子子树回根 之前子树不回根
- f[i][j][1]=f[i][j-k-2][1]+f[son][k][0]
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 using namespace std; 6 struct edge { int to,from; }e[510*2]; 7 int f[510][510][2],n,m,a[510],head[510],cnt; 8 void insert(int x,int y) { e[++cnt].to=y; e[cnt].from=head[x]; head[x]=cnt; } 9 void dp(int x,int fa) 10 { 11 for (int i=head[x];i;i=e[i].from) 12 { 13 if (e[i].to==fa) continue; 14 dp(e[i].to,x); 15 for (int j=m;j>=1;j--) 16 for (int k=0;k<=m;k++) 17 { 18 if (j-k>=2) 19 f[x][j][1]=max(f[x][j][1],f[x][j-k-2][1]+f[e[i].to][k][0]), 20 f[x][j][0]=max(f[x][j][0],f[x][j-k-2][0]+f[e[i].to][k][0]); 21 if (j-k>=1) f[x][j][1]=max(f[x][j][1],f[x][j-k-1][0]+f[e[i].to][k][1]); 22 } 23 } 24 for (int i=m;i>=1;i--) 25 { 26 f[x][i][0]=max(f[x][i][0],f[x][i-1][0]+a[x]); 27 f[x][i][1]=max(f[x][i][1],f[x][i-1][1]+a[x]); 28 } 29 } 30 int main() 31 { 32 freopen("dostavljac.in","r",stdin); 33 freopen("dostavljac.out","w",stdout); 34 scanf("%d%d",&n,&m); 35 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 36 for (int i=1;i<=n-1;i++) 37 { 38 int u,v; 39 scanf("%d%d",&u,&v); 40 insert(u,v); insert(v,u); 41 } 42 dp(1,0); 43 printf("%d",f[1][m][1]); 44 return 0; 45 }