luogu P2015 二叉蘋果樹

來源:互聯網
上載者:User

標籤: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 二叉蘋果樹

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.