• Luogu P1122 最大子树和


    题目链接

    题目大意:给定一棵树,每个点带点权,请你求出点权和最大的联通块和是多少。

    树形DP简单题

    f[x]为以x为根的子树,含x的联通块点权最大和。对于每个v(v∈son(x)),只要f[v]不是负数就把v选上。

    f[x]=∑max(f[son(x)],0)

    #include<iostream>
    #include<iomanip>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read() {
        char ch;
        bool bj=0;
        while(!isdigit(ch=getchar()))
            bj|=(ch=='-');
        int res=ch^(3<<4);
        while(isdigit(ch=getchar()))
            res=(res<<1)+(res<<3)+(ch^(3<<4));
        return bj?-res:res;
    }
    void printnum(int x) {
        if(x>9)printnum(x/10);
        putchar(x%10+'0');
    }
    inline void print(int x,char ch) {
        if(x<0) {
            putchar('-');
            x=-x;
        }
        printnum(x);
        putchar(ch);
    }
    int f[16005],a[16005],h[16005];
    struct Edge {
        int to,nxt;
    } w[16005<<1];
    int cnt,n;
    inline void AddEdge(int x,int y) {
        w[++cnt].to=y;
        w[cnt].nxt=h[x];
        h[x]=cnt;
    }
    int ans=-0x3f3f3f3f;
    void DFS(int x,int fa) {
        for(int i=h[x]; i; i=w[i].nxt) {
            int v=w[i].to;
            if(v==fa)continue;
            DFS(v,x);
            f[x]+=max(f[v],0);
        }
        f[x]+=a[x];
        ans=max(ans,f[x]);
    }
    signed main() {
        n=read();
        for(int i=1; i<=n; i++)a[i]=read();
        int x,y;
        for(int i=1; i<n; i++) {
            x=read();
            y=read();
            AddEdge(x,y);
            AddEdge(y,x);
        }
        DFS(1,0);
        print(ans,'
    ');
        return 0;
    }
  • 相关阅读:
    近期简单题炸分总结
    传输层中的端口号
    TCP的三次握手与四次挥手
    ppq的面试题总结
    一个C++源文件从文本到可执行文件经历的过程
    C++中的&符号的运用:引用、取地址和右值引用
    C++中的拷贝构造、赋值构造函数
    C++中的虚函数
    函数指针与回调函数
    C++中的智能指针
  • 原文地址:https://www.cnblogs.com/soledadstar/p/11379698.html
Copyright © 2020-2023  润新知