日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Tree of tree

 印度阿三17 2019-08-10

題意:
一棵結(jié)點帶權(quán)樹,大小(結(jié)點數(shù))為k的子樹的權(quán)值和最大為多少。

初步分析
這道題其實就是一道01背包問題只是是在樹上做而已。背包的總?cè)萘烤褪莐個結(jié)點(一定得剛好裝滿),每個物品的價值就是結(jié)點的權(quán)值w[i].注意,并不是隨便選取結(jié)點就行了。而是一定得是子樹。那么這一點我們要怎么實現(xiàn)呢。首先我們用dp[i][j]來表示以結(jié)點i為首的結(jié)點數(shù)為j的權(quán)值最大的一棵子樹。那么dp[i][j]的狀態(tài)方程怎么寫呢?dp[i][j]=max(dp[i][j],dp[i][j-w] dp[v][w])(v是結(jié)點i的子節(jié)點,1=<j<=cnt[i],0<w<j)注意我們是怎么保證dp[i][j]表示的是以結(jié)點i為首的子樹呢?新節(jié)點所能取得的最大結(jié)點數(shù)只能是j-1,因為dp[i][1]始終代表的是結(jié)點i,所以才能保證都是以結(jié)點i為首的子樹。而且由于是01背包所以我們的背包容量j從大到小更新,這樣保證所有的小值都是上一次子節(jié)點的更新值而不是重復使用當前結(jié)點的值(不然的話就變成完全背包了)。

直接上代碼

#include <iostream>
#include <string.h>
using  namespace std;
const int MAX_N=110;
const int MAX_M=220;
int w[MAX_N];
int dp[MAX_N][MAX_N];
int cnt[MAX_N];
int n,k,answer=0;

//我們這里用圖來儲存樹,在遍歷的時候通過一個father參數(shù)就可以轉(zhuǎn)化為樹了。沒有必要用一個father數(shù)組來儲存
int ans=0;
int head[MAX_N];
struct edge{
    int v;
    int next;
}eid[MAX_M];

void insert(int u,int v){
    eid[ans].v=v;
    eid[ans].next=head[u];
    head[u]=ans  ;
}

int read(){
    int w=1,s=0;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-'){
           w*=-1;
        }
        ch=getchar();
    }
    while(isdigit(ch)){
        s=(s<<1) (s<<3) ch-48;
        ch=getchar();
    }
    return s*w;
}
int dfs(int node,int father){
    cnt[node]=1;
    for(int i=head[node];i!=-1;i=eid[i].next){
        int v=eid[i].v;
        if(v==father) continue;
        cnt[node] =dfs(v,node);
    }
    dp[node][1]=w[node];

    for(int i=head[node];i!=-1;i=eid[i].next){
        int v=eid[i].v;
        if(v==father) continue;
        for(int j=cnt[node];j>=1;--j) {
            for (int m = 0; m <=cnt[v] && m<j ;   m) {
                dp[node][j] = max(dp[node][j], dp[node][j - m] dp[v][m]);
            }
        }
    }

    answer=max(answer,dp[node][k]);

    return cnt[node];
}

int main() {

    while(scanf("%d %d",&n,&k)!=EOF) {

        for (int i = 1; i <= n;   i) {
            w[i] = read();
        }
        memset(head, -1, sizeof(head));
        ans=0;
        for (int i = 0; i <MAX_N;   i) {
            for (int j = 0; j <MAX_N;   j) {
                dp[i][j] = 0;
            }
        }

        for (int i = 1; i <= n - 1;   i) {
            int x, y;
            x = read() 1;
            y = read() 1;

            insert(x, y);
            insert(y, x);
        }

        dfs(1, -1);
        cout <<answer<<endl;
        answer=0;
    }
    return 0;
}
來源:https://www./content-4-386351.html

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多