树形 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?
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 #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 }