Codeforces Contest 1092 problem F Tree with Maximum Cost —— 返回深度*值的dfs

82 篇文章 1 订阅

You are given a tree consisting exactly of n vertices. Tree is a connected undirected graph with n−1 edges. Each vertex v of this tree has a value av assigned to it.

Let dist(x,y) be the distance between the vertices x and y. The distance between the vertices is the number of edges on the simple path between them.

Let’s define the cost of the tree as the following value: firstly, let’s fix some vertex of the tree. Let it be v. Then the cost of the tree is ∑i=1ndist(i,v)⋅ai.

Your task is to calculate the maximum possible cost of the tree if you can choose v arbitrarily.

Input
The first line contains one integer n, the number of vertices in the tree (1≤n≤2⋅105).

The second line of the input contains n integers a1,a2,…,an (1≤ai≤2⋅105), where ai is the value of the vertex i.

Each of the next n−1 lines describes an edge of the tree. Edge i is denoted by two integers ui and vi, the labels of vertices it connects (1≤ui,vi≤n, ui≠vi).

It is guaranteed that the given edges form a tree.

Output
Print one integer — the maximum possible cost of the tree if you can choose any vertex as v.

Examples
inputCopy
8
9 4 1 7 10 1 6 5
1 2
2 3
1 4
1 5
5 6
5 7
5 8
outputCopy
121
inputCopy
1
1337
outputCopy
0

题意:

给你n个点组成的树,每个点都有一个权值,这个树的值是
在这里插入图片描述
dist(i,j)是这两个点的距离。

题解:

那么这道题我们就是遍历所有的点,看看哪个点的值最大。dfs下去的时候儿子的值就是父亲的值+除了儿子子树的点其它所有点的值-儿子子树节点的值=父亲节点的值+所有节点的值-2*子树节点的值。那我们要处理出来的就是每个点子树的值,和在根节点这个树的值,因为根节点是所有节点的父亲,这样会方便一点。
那么dis返回的是这个节点下面的(不包括这个节点)的值,sum就是带深度的和,因为a数组就是这个节点子树的和。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+5;
vector<int>vec[N];
ll a[N];
ll dis(int x,int fa)
{
    ll sum=0;
    for(int i=0;i<vec[x].size();i++)
    {
        if(vec[x][i]==fa)
            continue;
        sum+=dis(vec[x][i],x);
        sum+=a[vec[x][i]],a[x]+=a[vec[x][i]];
    }
    return sum;
}
ll maxn;
void dfs(int x,int fa,ll sum)
{
    ll s=sum+(fa?a[1]-2*a[x]:0);
    maxn=max(maxn,s);
    for(int i=0;i<vec[x].size();i++)
    {
        if(vec[x][i]==fa)
            continue;
        dfs(vec[x][i],x,s);
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    int x,y;
    for(int i=1;i<n;i++)
        scanf("%d%d",&x,&y),vec[x].push_back(y),vec[y].push_back(x);
    ll d=dis(1,0);
    dfs(1,0,d);
    printf("%lld\n",maxn);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值