標籤:http freopen asp 總結 zcl const oid namespace cas
題目:題目背景
URAL:http://acm.timus.ru/problem.aspx?space=1&num=1018
題目描述
有一棵蘋果樹,如果樹枝有分叉,一定是分 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
輸出
21
題解:
dp[i][j]:表示i號點所在子樹(包括自己)共保留j個點可以留下的最多蘋果
注意這道題我把保留m條邊變成保留m+1個點來求的·····
另外注意在進行樹形dp dfs的時候用記憶化搜尋·····
代碼:
#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>#include<cctype>#include<cstring>#include<string>#include<algorithm>using namespace std;const int N=105;int first[N],next[N*2],go[N*2],val[N*2],tot;int n,m;int dp[N][N];inline void comb(int a,int b,int c){ next[++tot]=first[a],first[a]=tot,go[tot]=b,val[tot]=c; next[++tot]=first[b],first[b]=tot,go[tot]=a,val[tot]=c; }inline void dfs(int u,int fa,int Val,int k){ if(u==0||k==0) { dp[u][k]=0; return; } if(dp[u][k]!=-1) return; dp[u][k]=0; for(int i=0;i<k;i++) { int l=0,r=0,vl,vr; for(int e=first[u];e;e=next[e]) { int v=go[e]; if(v==fa) continue; if(l==0) l=v,vl=val[e]; else { r=v,vr=val[e]; break; } } dfs(l,u,vl,i); dfs(r,u,vr,k-i-1); dp[u][k]=max(dp[l][i]+dp[r][k-i-1]+Val,dp[u][k]); } return;}int main(){ freopen("a.in","r",stdin); scanf("%d%d",&n,&m); m++; memset(dp,-1,sizeof(dp)); int a,b,c; for(int i=1;i<n;i++) { scanf("%d%d%d",&a,&b,&c); comb(a,b,c); } dfs(1,0,0,m); cout<<dp[1][m]<<endl; return 0;}
刷題總結——二叉蘋果樹(ssoj樹形dp+記憶化搜尋)