题目描述
有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)
这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。
我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树
2 5 / 3 4 / 1 现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。
给定需要保留的树枝数量,求出最多能留住多少苹果。
输入输出格式
输入格式:
第1行2个数,N和Q(1<=Q<= N,1<N<=100)。
N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。
每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。
每根树枝上的苹果不超过30000个。
输出格式:
一个数,最多能留住的苹果的数量。
输入输出样例
输入样例#1:
5 2 1 3 1 1 4 10 2 3 20 3 5 20
输出样例#1:
21
二……二叉树……
二叉树大概只要DFS就可以了呀……写完树规才反应过来。
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=210; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 struct edge{ 17 int v,nxt; 18 int dis; 19 }e[mxn]; 20 int hd[mxn],mct=0; 21 void add_edge(int u,int v,int dis){ 22 e[++mct].v=v;e[mct].nxt=hd[u];e[mct].dis=dis;hd[u]=mct; 23 return; 24 } 25 int n,q; 26 int f[mxn][mxn]; 27 int num[mxn]; 28 int w[mxn]; 29 void DP(int u,int fa){ 30 for(int i=1;i<=num[u];i++){ 31 f[u][i]=w[u]; 32 } 33 for(int i=hd[u];i;i=e[i].nxt){ 34 int v=e[i].v; 35 if(v==fa)continue; 36 DP(v,u); 37 for(int j=num[u];j;j--){ 38 for(int k=min(num[v],j-1);k>=0;k--){ 39 f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]); 40 } 41 } 42 } 43 return; 44 } 45 void Build(int u,int fa){ 46 num[u]++; 47 for(int i=hd[u];i;i=e[i].nxt){ 48 int v=e[i].v; 49 if(v==fa)continue; 50 w[v]=e[i].dis; 51 Build(v,u); 52 num[u]+=num[v]; 53 } 54 return; 55 } 56 int main(){ 57 int i,j; 58 n=read();q=read(); 59 int u,v,d; 60 for(i=1;i<n;i++){ 61 u=read();v=read();d=read(); 62 add_edge(u,v,d); 63 add_edge(v,u,d); 64 } 65 Build(1,0); 66 DP(1,0); 67 printf("%d ",f[1][q+1]); 68 return 0; 69 }