标签:
Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %lld & %llu |
Description
Input
Output
Sample Input
2 1
0 11
1 2
3 2
0 1 2
1 2
1 3
Sample Output
11
2
Source
若当前走到了结点x,已经走了y步,除了走向子树外,还有另一选择:返回父节点,去父节点的其他子树。
所以比一般的树状DP多加一维状态,记录有没有返回当前结点。0表示要回,1表示不回。
懒得写分析了,复制一份233
dp[root][j][0] = MAX (dp[root][j][0] , dp[root][j-k][0] + dp[son][k-2][0]);//从s出发,要回到s,需要多走两步s-t,t-s,分配给t子树k步,其他子树j-k步,都返回
dp[root][j]][1] = MAX( dp[root][j][1] , dp[root][j-k][0] + dp[son][k-1][1]) ;//先遍历s的其他子树,回到s,遍历t子树,在当前子树t不返回,多走一步
dp[root][j][1] = MAX (dp[root][j][1] , dp[root][j-k][1] + dp[son][k-2][0]);//不回到s(去s的其他子树),在t子树返回,同样有多出两步
by键盘上的舞者
我实际写的时候0和1与上面说的相反。
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 const int mxn=240; 9 struct edge{ 10 int v; 11 int nxt; 12 }e[mxn]; 13 int hd[mxn],mct=0; 14 void add_edge(int u,int v){ 15 e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct; 16 return; 17 } 18 int f[mxn][mxn][2];//第三维0表示不返回根节点,1表示返回根节点 19 int w[mxn]; 20 int n,m; 21 void dp(int u,int fa){ 22 int i,j,k; 23 for(i=hd[u];i;i=e[i].nxt){ 24 int v=e[i].v; 25 if(v==fa)continue; 26 dp(v,u); 27 for(j=m;j;--j){ 28 for(k=1;k<=j;++k){ 29 f[u][j][1]=max(f[u][j][1],f[u][j-k][1]+f[v][k-2][1]); 30 f[u][j][0]=max(f[u][j][0],f[u][j-k][1]+f[v][k-1][0]); 31 f[u][j][0]=max(f[u][j][0],f[u][j-k][0]+f[v][k-2][1]); 32 } 33 } 34 } 35 return; 36 } 37 int main(){ 38 while(scanf("%d%d",&n,&m)!=EOF){ 39 memset(e,0,sizeof e); 40 memset(hd,0,sizeof hd); 41 memset(f,0,sizeof 0); 42 mct=0; 43 int i,j; 44 for(i=1;i<=n;i++){ 45 scanf("%d",&w[i]); 46 for(j=0;j<=m;j++){ 47 f[i][j][0]=f[i][j][1]=w[i]; 48 } 49 } 50 int u,v; 51 for(i=1;i<n;i++){ 52 scanf("%d%d",&u,&v); 53 add_edge(u,v); 54 add_edge(v,u); 55 } 56 dp(1,0); 57 printf("%d\n",f[1][m][0]); 58 } 59 return 0; 60 }
标签:
原文地址:http://www.cnblogs.com/SilverNebula/p/5918417.html