zoukankan      html  css  js  c++  java
  • 牛客多校Round 2

    Solved:3

    rank:187

    H.travel

    题意:给一颗带有点权的树 找三条不相交的链 使得点权最大

    题解:使用树形DP dp[x][i][0/1] 表示x节点选择i条链 有没有经过x的链

       对于每一个回溯的状态 下面的结点已经处理好了

       但是处理当前结点时还有一种有两条经过x的链 实际上他们可以合成一条链

       为了避免重复计算 经过当前结点的权值在更新时计算

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n;
    ll val[400005];
    ll dp[400005][4][2];
    vector<int> g[400005];
    
    void dfs(int x, int fa)
    {
        ll tmp[4][3]; ll f[4][3];
        for(int i = 0; i < 4; i++) tmp[i][0] = tmp[i][1] = tmp[i][2] = 0;
        for(int i = 0; i < g[x].size(); i++)
        {
            int v = g[x][i];
            if(v == fa) continue;
            dfs(v, x);
            memcpy(f, tmp, sizeof(tmp));
    
            for(int a = 0; a < 4; a++)
                for(int b = 0; b < 4; b++)
                {
                    if(a + b > 3) continue;
                    for(int c = 0; c < 3; c++)
                        for(int d = 0; d < 2; d++)
                        {
                            if(c + d > 2) continue;
                            tmp[a + b][c + d] = max(tmp[a + b][c + d], f[a][c] + dp[v][b][d]);
                        }
                }
        }
        for(int i = 0; i < 4; i++)
        {
            dp[x][i][0] = max(dp[x][i][0], tmp[i][0]);
            dp[x][i][1] = max(dp[x][i][1], tmp[i][1] + val[x]);
    
            if(i < 3)
            {
                for(int j = 0; j < 2; j++)
                    for(int k = j + 1; k < 3; k++)
                        dp[x][i + 1][j] = max(dp[x][i + 1][j], tmp[i][k] + val[x]);
            }
        }
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%lld", &val[i]);
        for(int i = 1; i < n; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        dfs(1, -1);
        ll ans = 0;
        for(int i = 0; i < 4; i++) ans = max(ans, dp[1][i][0]);
        printf("%lld
    ", ans);
        return 0;
    }
    /*
    13
    10 10 10 10 10 1 10 10 10 1 10 10 10
    1 2
    2 3
    3 4
    4 5
    2 6
    6 7
    7 8
    7 9
    6 10
    10 11
    11 12
    11 13
    */
    View Code

       

  • 相关阅读:
    关于回调地狱
    node.js 关于跨域和传递给前台参数
    关于js的当前日期的格式化,和两个日期之间的相减的天数
    CSS 关于让页面的高度达到电脑屏幕的底部
    前端 为什么我选择用框架而不是Jquery
    关于webpack打包图片的路径问题
    关于webpack打包js和css
    微信小程序网络请求的setDate
    WinSocket聊天程序实例(多线程)
    Orcal的JDBC数据连接方式
  • 原文地址:https://www.cnblogs.com/lwqq3/p/9349715.html
Copyright © 2011-2022 走看看