• codeforces 743D


    题意

    给一颗树取出两个不相互包含的子树使权值和最大


    当然是选择DP辣~很容易想到枚举以每一个点为根的子树 找到对于这棵子树来说,之外的权值和最大的子树。第一遍dfs可以找出每个点的子树大小以及以每个点为根 所有子树的最大子树,以及这个子树所在的这个点的儿子节点,以及其他个儿子节点找一颗第二大子树。

    所以对于每一个树来说,与它对应的最大的  另一棵最大权值子树    在父亲节点对应的最大权值子树    以及    父亲节点的另外孩子包含的最大子树上(感觉有点绕==

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define F    first  
    #define S     second
    #define mem(a,b)    memset(a,b,sizeof(a))
    using namespace std;
    #define INF        0x7ffffffffffffff
    typedef long long int LL;
    #define MAX_N        200005
    LL w[MAX_N];
    struct no
    {
        int v,nexr;    
    }ed[MAX_N*3];
    int stu[MAX_N];
    int col = 0;
    void add(int u , int v){
        ed[col].v = v;
        ed[col].nexr = stu[u];
        stu[u] = col++;
    }
    pair<LL,pair<LL,LL> > ans[MAX_N];
    bool flag[MAX_N];
    int set[MAX_N];
    int cnt[MAX_N];
    void dfs(int u){
        flag[u] = true;
        ans[u].F = w[u];
        for (int i = stu[u]; i != -1  ; i = ed[i].nexr)
        {
            int v = ed[i].v;
            if(flag[v])
                continue;
            dfs(v);
            ans[u].F+=ans[v].F;
            if(ans[v].S.F>ans[u].S.F||ans[v].F>ans[u].S.F){
                set[u]  = v;
                ans[u].S.S = ans[u].S.F;
                ans[u].S.F = max(ans[v].S.F, ans[v].F);
            }
            else if(ans[v].S.F>ans[u].S.S||ans[v].F>ans[u].S.S){
                ans[u].S.S = max(ans[v].S.F,ans[v].F);
            }
        }
    }
    LL res[MAX_N];
    void dfs2(int u){
        flag[u] = true;
        for (int i = stu[u]; i != -1  ; i = ed[i].nexr)
        {
            int v = ed[i].v;
            if(flag[v])
                continue;
            if(set[u] != v)
                res[v] = max (ans[u].S.F,res[u]);
            else 
                res[v] = max (ans[u].S.S,res[u]);
            dfs2(v);
        }
    }
    
    int main(int argc, char const *argv[])
    {
        int n;
        mem(stu,-1);
        scanf("%d",&n);
        for (int i = 1; i <= n ; ++i){
            scanf("%I64d",&w[i]);
            ans[i].F = ans[i].S.F = ans[i].S.S = res[i] = -INF;
        }
        int u , v;
        for (int i = 1; i <= n-1 ; ++i)
        {
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
            cnt[u]++;
            cnt[v]++;
        }
        dfs(1);
        mem(flag,false);
        dfs2(1);
        LL pri = -INF;
        for (int i = 1; i <= n ; ++i)
        {
            if(res[i]!=-INF){
                pri = max(res[i]+ans[i].F,pri);
            }
        }
        if(pri==-INF)
            printf("Impossible
    ");
        else
            printf("%I64d
    ",pri );
        return 0;
    }
  • 相关阅读:
    广播BroadcastReceiver(2)
    hunnu11544:小明的烦恼——找字符串
    Systemd启动图形界面过程
    大数据.......
    2014百度之星第一题Energy Conversion
    基于zookeeper简单实现分布式锁
    LeetCode OJ 215. Kth Largest Element in an Array 堆排序求解
    Leetcode
    Linux文件系统(七)---系统调用之open操作(一)
    Go语言Slice操作.
  • 原文地址:https://www.cnblogs.com/miamiao/p/6954047.html
Copyright © 2020-2023  润新知