zoukankan      html  css  js  c++  java
  • “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛 A.点对最大值(树的直径/树形DP)

    坑比输入,比赛时没A掉可惜了

    题目描述

    这里有一棵树,每个点和每条边都存在一个价值。对于树上点对的价值,包括点对的起点和终点以及路径上边权值之和,不包括路径上其他点值。
    求这颗树上最大的点对价值为多少。点对至少需要两个点。

     

    输入描述:

    输入t,代表有t组样例。每组样例第一行输入n,代表有n个点。接下来有n-1行,第i行有a[i]和b[i],代表a[i]节点与i节点存在一条边,且边的值为b[i],2<=i<=n。接下来一行有n个值c[j],代表每个节点j的价值,1<=j<=n。
    (t<=10,n>1,n<1e6,a[i]<i,-500<=b[i]<=500,-500<=c[j]<=500)

    输出描述:

    输出最大的点对价值

     

    首先注意这题输入比较坑,n那一行实际上是第一行,然后从第二行开始输入边…

    注意这个题的点对价值的定义:起点终点加上路径上的边权总和。那么可以联想到树的直径,关键在于两个端点怎么处理。其实很简单,只需要把d数组初始化成对应的点权即可。这里我套了蓝书的板子,此处d[x]的含义为:从节点x出发走向x为根的子树,能够到达的最远价值处(包含路径端点的点权以及经过的边的边权之和,不包含x的点权)。对于这个题而言,假设当前处理到的点的度不为1,那么这个初始化了的d[x]肯定会被后续更新掉,假设度为1,联想到求树的直径时,dfs到了叶子时其实啥都没干,叶子节点的d值也没有被更新,那么这个题要加上端点,我就把它初始化成点权,问题完美解决。

    #include <bits/stdc++.h>
    #define N 1000006
    using namespace std;
    int head[N],ver[2*N],edge[2*N],Next[2*N],p[N],tot=0,d[N],n;//d[x]为不包含本点的从x出发能走的最远路径和 (包括最远点的端点值 不包括x 
    bool v[N];
    long long ans;
    void add(int x,int y,int z)
    {
        ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
    }
    void dp(int x)
    {
        v[x]=1;
        int i;
        for(i=head[x];i;i=Next[i])
        {
            int y=ver[i];
            if(v[y])continue;
            dp(y);
            if(ans<(long long)d[x]+d[y]+edge[i])
            {
                ans=(long long)d[x]+d[y]+edge[i];
            }
            d[x]=max(d[x],d[y]+edge[i]);
        }
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            tot=0;
            ans=-1e18;
            memset(head,0,sizeof(head));
            memset(ver,0,sizeof(ver));
            memset(edge,0,sizeof(edge));
            memset(Next,0,sizeof(Next));
            memset(d,0,sizeof(d));
            memset(v,0,sizeof(v));
            int i;
            cin>>n;
            for(i=2;i<=n;i++)
            {
                int a,b;
                cin>>a>>b;
                add(i,a,b);
                add(a,i,b);
            }
            for(i=1;i<=n;i++) 
            {
                scanf("%d",&p[i]);
                d[i]=p[i];
            }
            dp(1);
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Leetcode 214. Shortest Palindrome
    Leetcode 5. Longest Palindromic Substring
    windows环境下MySQL-5.7.12-winx64下载安装与配置
    随机森林(Random Forests)
    机器学习基石笔记3——在何时可以使用机器学习(3)
    Linux服务器配置---ssh配置
    Linux基础命令---more
    Linux服务器---流量监控ntop
    Linux基础命令---gunzip
    Linux服务器---ssh登录
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/13021478.html
Copyright © 2011-2022 走看看