树形 dp

// ACM训练联盟周赛     C. Teemo's tree problem

There is an apple tree in Teemo's yard. It contains n nodes and n-1 branches, and the node 1 is always the root of the tree. Today, Teemo's father will go out for work. So Teemo should do his father's job in the family: Cut some branches to make the tree more beautiful. His father's told him that he should cut some branches, finally, the tree should just contains q branches. But when Teemo start to cut, he realizes that there are some apples in the branches( For example, there are 10 apples in the branches which connecting node 1 and node 4). So Teemo not only wants to achieve his father's order, but also wants to preserve apples as much as possible. Can you help him?

 
 
 
 
 
1
2   5
2
 \ / 
3
  3   4
4
   \ /
5
    1
 
 

Input Format

  • The first line of the input contains an integer T(1<=T<=10) which means the number of test cases.
  • For each test case, The first line of the input contains two integers n,q(3<=n<=100,1<=q<=n-1), giving the number of the node and the number of branches that the tree should preserve.
  • In the next n-1 line, each line contains three integers u,v,w(1<=u<=n,1<=v<=n,u!=v,1<=w<=100000), which means there is a branch connecting node u and node v, and there are w apple(s) on it.

Output Format

Print a single integer, which means the maximum possible number of apples can be preserved.

样例输入

1
5 2
1 3 1
1 4 10
2 3 20
3 5 20

样例输出

21


 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<vector>
 7 #define N 209
 8 using namespace std;
 9 #define ll long long 
10 #define mem(a,b)  memset(a,b,sizeof(a))
11 #define inf 0x3f3f3f3f
12 int t,n,q;
13 int u,v,w,head[N],val[N];
14 int num[N];//num[i]: 包含i在内及其后面所有点的个数
15 int dp[N][N]; //dp[i][j] :以i为“根”,取j个点可获的最大价值
16 struct Edge{
17     int from,to,nex,w;
18 }e[N];
19 int cnt;
20 void init()
21 {
22     mem(head,-1);//-1,因为cnt初始化为了0
23     mem(val,0);
24     mem(dp,0);
25     mem(num,0);
26     cnt=0;
27 }
28 void add(int u,int v,int w){
29     e[cnt].from=u;
30     e[cnt].to=v;
31     e[cnt].w=w;
32     e[cnt].nex=head[u];
33     head[u]=cnt++;
34 }
35 void getval(int u){
36     for(int i=head[u];i!=-1;i=e[i].nex){
37         int v=e[i].to;
38         if(val[v]==0){//找过的不会在找了
39         val[v]=e[i].w;//除根节点外把边的值赋给点
40         getval(v);
41         }
42     }
43 }
44 int  dfs(int u,int fa)
45 {
46     num[u]=1;
47     for(int i=head[u];i!=-1;i=e[i].nex){
48         int v=e[i].to;
49         if(v==fa) continue;
50         num[u]+=dfs(v,u);
51     }
52     dp[u][1]=val[u];//只有自己,因此val[1]==0 :去掉所有的边才会只有1 
53     for(int i=head[u];i!=-1;i=e[i].nex){
54         int v=e[i].to;
55         if(v==fa) continue;
56         for(int j=num[u];j>=1;j--){//逆序,若正序比如 j==1 ,无法更新,后面的也会出现错误
57             for(int k=1;k<j&&k<=num[v];k++){
58                 dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
59             }
60         }
61     }
62     return num[u];
63 }
64 int  main()
65 {
66     scanf("%d",&t);
67     while(t--)
68     {
69         init();
70         scanf("%d%d",&n,&q);
71         for(int i=0;i<n-1;i++){
72             scanf("%d%d%d",&u,&v,&w);
73             add(u,v,w);
74             add(v,u,w);//无向图
75         }
76         val[1]=inf;//不是0就可以
77         getval(1);
78         val[1]=0;
79         dfs(1,0);
80         printf("%d\n",dp[1][q+1]);//q条边对应q+1个点
81     }
82     return 0;
83 }

 

posted on 2018-08-23 16:58  cltt  阅读(157)  评论(0编辑  收藏  举报

导航