標籤:turn read algorithm 刪除 algo enter 蘋果 isp float
P2015 二叉蘋果樹題目描述
有一棵蘋果樹,如果樹枝有分叉,一定是分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 21 3 11 4 102 3 203 5 20
輸出範例#1:
21
樹上的背包問題,很容易就想到如果刪除一個子節點,那麼以這個節點的棵子樹就會全部刪除,那麼對這個子樹刪除的節點就不能超過子節點個數。
所以我們先dfs一邊,求出有多少一個節點有多少子節點,並標記處father,保證不會到father
f[i][j]<在i這個子樹中刪除j個邊的最大值,然後貪心維護最大就好了
#include<iostream>#include<cstdlib>#include<cstdio>#include<algorithm>#include<queue>#define ll long long using namespace std;const int maxn=150;int read(){ int an=0,f=1;char ch=getchar(); while(!(‘0‘<=ch&&ch<=‘9‘)){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return f*an;}int f[maxn],dp[maxn][maxn],cnt,fa[maxn],son[maxn],Q,n;bool vis[maxn],vis2[maxn];struct saber{int to,nex,wi;}b[maxn<<1];void add(int x,int y,int z){ cnt++; b[cnt].nex=f[x]; b[cnt].to=y; f[x]=cnt; b[cnt].wi=z;}void dfs(int x){ vis[x]=1;son[x]=1; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(!vis[v]){ dfs(v); fa[v]=x; son[x]+=son[v]; } }}void DP(int x){ vis2[x]=1; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(fa[x]!=v){ DP(v); for(int j=min(son[x],Q);j>0;j--) for(int k=min(j,Q);k>0;k--) dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[v][k-1]+b[i].wi); } }}int main(){ n=read();Q=read(); for(int i=1;i<n;i++){ int x=read(),y=read(),z=read(); add(x,y,z); add(y,x,z); } dfs(1); DP(1); cout<<dp[1][Q]; return 0;}
apple_tree
by:s_a_b_e_r
樓上一直堅持兩遍dfs,其實一遍就好了啊qwq
而且既然只向下dp,存單向邊就可以啦(但是要存一下father)
因為是二叉樹所以非常好辦
如果點x的子樹一共要保留i根樹枝
肯定是一部分(j)分給左子樹,剩下的(i-j)給右子樹
於是就可以愉快地填表DP了^_^
#include<iostream>#include<cstdio>using namespace std;const int N=109;int n,q,p[N],fa[N],f[N][N],cnt,son[N];struct edge{int to,nex,val;}e[N<<1];void add(int u,int v,int w){ ++cnt; e[cnt].to=v; e[cnt].nex=p[u]; p[u]=cnt; e[cnt].val=w;}void dfs(int u){ son[u]=1; for(int i=p[u];i;i=e[i].nex) { int v=e[i].to; dfs(v); son[u]+=son[v]; for(int j=min(q,son[u]);j>=1;--j) for(int k=min(j,son[u]);k>=1;--k) f[u][j]=max(f[u][j],f[u][j-k]+f[v][k-1]+e[i].val); }}int main(){ scanf("%d%d",&n,&q); for(int i=1;i<n;++i) { int x,y,z; scanf("%d%d%d",&x,&y,&z); if(fa[y]){fa[x]=y;add(y,x,z);} else {fa[y]=x;add(x,y,z);} } dfs(1); cout<<f[1][q]<<endl; return 0;}
apple apple tree
by:wypx
s:I have an apple……
w:I have an another apple……apple tree!!!
luogu P2015 二叉蘋果樹