zoukankan      html  css  js  c++  java
  • luogu P1122(树形dp)

    传送门

    题意:

    给你一个有(n)个结点的树,每个结点有一个权值,现在你可以把任意一条边断掉,此时会形成两棵树,你需要舍去其中一棵树,并统计另外一棵树上所有结点的权值。现在你可以做若干次上述操作,问你可以获得的最大权值。

    分析:

    这是一个比较经典的树形(dp)的模型。

    我们设(dp[i])为以结点(i)为根的树的最大权值,那么对于它的儿子,我们有选和不选(不选代表把儿子的子树都割掉了)两种状态。因此我们不难发现,当前的状态可以由儿子的选和不选这两种状态转移过来(若选取该儿子,则我们只需要令权值增加(dp[son[i]])即可,否则增加(0)),故有状态转移方程(dp[i]+=max(dp[son[i],0])) 。而我们在进行(dfs)的过程正好是完成了自底向上更新的过程,因此我们只需要在(dfs)的过程中进行更新即可。

    代码

    #include <bits/stdc++.h>
    #define maxn 16005
    using namespace std;
    struct Node{
        int to,next;
    }q[maxn<<1];
    int head[maxn],cnt=0,dp[maxn],val[maxn],tmp[maxn],n;
    int vis[maxn],maxx=0;
    void add_edge(int from,int to){
        q[cnt].to=to;
        q[cnt].next=head[from];
        head[from]=cnt++;
    }
    void init(){
        memset(head,-1,sizeof(head));
        cnt=0;
    }
    void dfs(int x){
        dp[x]=val[x];
        vis[x]=1;
        for(int i=head[x];i!=-1;i=q[i].next){
            int to=q[i].to;
            if(vis[to]) continue;
            dfs(to);
            dp[x]+=max(dp[to],0);
        }
        maxx=max(maxx,dp[x]);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
        }
        init();
        for(int i=1;i<n;i++){
            int from,to;
            scanf("%d%d",&from,&to);
            add_edge(from,to);
            add_edge(to,from);
        }
        dfs(1);
        printf("%d
    ",maxx);
        return 0;
    }
    
    
    
  • 相关阅读:
    ssh
    步进器&分栏控制器
    一些过期的整理前端代码
    进度条和滑动条
    UISwitcher
    定时器
    创建window
    iOS开发---UIButton 1 //创建一个可以显示图片的按钮。
    iOS开发---UILabel
    今日头条前端编程题
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11180880.html
Copyright © 2011-2022 走看看