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\n",i,val[i]); 65 */ 66 val[1]=0; 67 dfs(1,0); 68 int ans=dp[1][rmn+1]; 69 printf("%d\n",ans); 70 } 71 return 0; 72 }
posted on 2018-07-29 21:05 Emiya_Kiritsugu 阅读(211) 评论(0) 编辑 收藏 举报