| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 6654 | Accepted: 2197 |
Description
Input
Output
Sample Input
2 1 0 11 1 2 3 2 0 1 2 1 2 1 3
Sample Output
11 2
题意:一个n个节点的树,每个节点都有一个权值,从1出发,走k步,所能得到的最大权值,每个节点的权值只能算一次。
经典树形dp,理解了好久,终于看懂了。
代码:
/* ***********************************************
Author :xianxingwuguan
Created Time :2014-2-4 14:10:17
File Name :1.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
int head[110],tol,dp[110][310][2],weight[110],m;
struct node{
int next,to;
}edge[300];
void add(int u,int v){
edge[tol].to=v;
edge[tol].next=head[u];
head[u]=tol++;
}
void dfs(int u,int fa){
for(int i=0;i<=m;i++)
dp[u][i][0]=dp[u][i][1]=weight[u];
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(v==fa)continue;
dfs(v,u);
for(int j=m;j>=0;j--)
for(int k=0;k<=j;k++){
dp[u][j+2][0]=max(dp[u][j+2][0],dp[u][j-k][0]+dp[v][k][0]);//u返回,v返回
dp[u][j+2][1]=max(dp[u][j+2][1],dp[u][j-k][1]+dp[v][k][0]);//从u出发到v,v返回经过u访问u的其他子树不返回。
dp[u][j+1][1]=max(dp[u][j+1][1],dp[u][j-k][0]+dp[v][k][1]);//从u的其他子树返回u,再访问u的子树v并不返回。
}
}
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int i,j,k,n;
while(~scanf("%d%d",&n,&m)){
memset(head,-1,sizeof(head));tol=0;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
scanf("%d",&weight[i]);
for(i=1;i<n;i++){
scanf("%d%d",&j,&k);
add(j,k);
add(k,j);
}
dfs(1,-1);
printf("%d\n",dp[1][m][1]);
}
return 0;
}
原文:http://blog.csdn.net/xianxingwuguan1/article/details/18923397