Teemo's tree problem

题目链接 : https://nanti.jisuanke.com/t/29228

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?

2  5
  /
 3   4
   /
   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号点为根节点的 n个结点的树, n-1 条边均有权值,现在把这棵树在保留根节点的情况下剪成一棵 q条边的树并且使剩余的树权值最大。(注意 : 减去一条边该边后面的边都会被去掉)

这应该是一道十分经典的树形dp 。

除根节点外将 边的权值赋给点,val[i]记录i号点的权值。

have[i] 表示i号点及其之后的所有点的个数, dp[i][j]表示在i号点为"根"的情况下共保留j个点的最大权值。

做题时想到了边值赋点,却不知如何dp,树形dp还是见少了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define pb(x) push_back((x))
 4 
 5 typedef long long ll;
 6 const int INF=0x3f3f3f3f;
 7 struct Edge{
 8     int to;
 9     int wei;
10     Edge(int v,int w):to(v),wei(w) {}
11 };
12 vector< Edge > G[101];
13 int val[101];
14 int have[101];
15 int dp[101][101];
16 
17 void getVal(int u){
18     for( auto e : G[u]){
19         if(val[e.to]==0){
20             val[e.to]=e.wei;
21             getVal(e.to);
22         }
23     }
24 }
25 
26 int dfs(int u,int fa){
27     have[u]=1;
28     for( auto e : G[u]){
29         if(e.to==fa) continue;
30         have[u]+=dfs(e.to,u);
31     }
32     dp[u][1]=val[u];
33     for( auto e : G[u]){
34         if(e.to==fa) continue;
35         for(int tot=have[u];tot>=1;tot--){
36             for(int i=1;i<tot&&i<=have[e.to];++i){
37                 dp[u][tot]=max(dp[u][tot],dp[u][tot-i]+dp[e.to][i]);
38             }
39         }
40     }
41     return have[u];
42 }
43 
44 int main(){
45     int T;
46     scanf("%d",&T);
47     while(T--){
48         int N,rmn;
49         scanf("%d%d",&N,&rmn);
50         for(int i=1;i<=N;++i) G[i].clear();
51         for(int i=0;i<N-1;++i){
52             int u,v,w;
53             scanf("%d%d%d",&u,&v,&w);
54             G[u].pb(Edge(v,w));
55             G[v].pb(Edge(u,w));
56         }
57         memset(val,0,sizeof(val));
58         memset(have,0,sizeof(have));
59         memset(dp,0,sizeof(dp));
60         val[1]=INF;
61         getVal(1);
62         /*
63         for(int i=1;i<=N;++i)
64             printf("%d : %d
",i,val[i]);
65             */
66         val[1]=0;
67         dfs(1,0);
68         int ans=dp[1][rmn+1];
69         printf("%d
",ans);
70     }
71     return 0;
72 }
View Code
原文地址:https://www.cnblogs.com/Kiritsugu/p/9387655.html