hdu 4169 树形dp

hdu 4169

题意:给定一棵树,每一节点都有一权值,要求选出总权值最大的K个点,同时这K个点中任意一个点都不能是其他节点的祖先。

节点数太多了,150000 ,爆内存的,所以开了一个临时数组保存

注意优化 子分支的状态数 复杂度O(n*k^2)

 

 1 #include<iostream>
2 #include<cstring>
3 #include <cstdio>
4 #include<string>
5 #include<queue>
6 #include<vector>
7 #include<map>
8 #include <set>
9 #include<ctime>
10 #include<cmath>
11 #include <cstdlib>
12 #include<algorithm>
13 #include <climits>
14 using namespace std;
15
16 #define LL long long
17 #define nMAX 150001
18 #define mMAX 301
19 int dp[mMAX];
20 int w[nMAX],start[nMAX];
21 int n,m,p;
22 vector<int> G[nMAX];
23 int dfs(int u,int *dp){
24 int best[mMAX]; fill(best,best+m+1,0);
25 int t=0;
26 for(int i=0;i<G[u].size();i++){
27 int v=G[u][i];
28 fill(dp,dp+m+1,0);
29 int now=dfs(v,dp);
30 for(int j=t;j>=0;j--)
31 for(int k=1;k<=now&&j+k<=m;k++)
32 if((dp[k]&&best[j])
33 ||(!j&&dp[k]))
34 best[j+k]=max(best[j+k],best[j]+dp[k]);
35 t+=now;
36 }
37 dp[1]=max(w[u],best[1]);
38 for(int i=2;i<=m;i++) dp[i]=best[i];
39 if(!G[u].size()) t++;
40 return t;
41 }
42 int main(){
43 while(scanf("%d%d",&n,&m)!=EOF){
44 int root;
45 p=0;
46 for(int i=1;i<=n;i++) G[i].clear();
47 for(int i=1;i<=n;i++){
48 int u;
49 scanf("%d%d",&u,&w[i]);
50 if(u==0) root=i;
51 else G[u].push_back(i);
52 }
53 dfs(root,dp);
54 int ans=dp[m];
55 if(ans) printf("%d\n",ans);
56 else printf("impossible\n");
57 }
58 }


以上参考 http://www.cnblogs.com/nanke/archive/2012/03/04/2379261.html

另一种优化 :复杂度 O(n*k)

 1 #include<iostream>
2 #include<cstring>
3 #include <cstdio>
4 #include<string>
5 #include<queue>
6 #include<vector>
7 #include<map>
8 #include <set>
9 #include<ctime>
10 #include<cmath>
11 #include <cstdlib>
12 #include<algorithm>
13 #include <climits>
14 using namespace std;
15
16 #define LL long long
17 #define nMAX 150001
18 #define mMAX 301
19 int dp[mMAX];
20 int w[nMAX],start[nMAX];
21 int n,m,p;
22 vector<int> G[nMAX];
23 void dfs(int u,int *dp){
24 int best[mMAX];
25 copy(dp,dp+m+1,best);
26 for(int i=0;i<G[u].size();i++){
27 int v=G[u][i];
28 dfs(v,best);
29 }
30 for(int i=m;i>=1;i--){
31 if( (dp[i-1]||!(i-1) )&&
32 dp[i-1]+w[u]>best[i]) dp[i]=dp[i-1]+w[u];
33 else dp[i]=best[i];
34 }
35 }
36 int main(){
37 while(scanf("%d%d",&n,&m)!=EOF){
38 int root;
39 p=0;
40 for(int i=1;i<=n;i++) G[i].clear();
41 for(int i=1;i<=n;i++){
42 int u;
43 scanf("%d%d",&u,&w[i]);
44 if(u==0) root=i;
45 else G[u].push_back(i);
46 }
47 fill(dp,dp+m+1,0);
48 dfs(root,dp);
49 int ans=dp[m];
50 if(ans) printf("%d\n",ans);
51 else printf("impossible\n");
52 }
53 }



 

 

posted @ 2012-03-27 22:16  HaoHua_Lee  阅读(210)  评论(0编辑  收藏  举报