树上最大得分-LintCode

204 篇文章 0 订阅

一棵 n 个结点的多叉树,结点编号为[0, n - 1],根结点的编号为 0。每个结点有一个收益,到这个结点了,就可以加上这个结点的收益;每条边有一个花费,沿着这条边走,就要减去这条边的花费。问,从根结点走到任意一个叶子结点的总得分(总得分 = 总收益 - 总花费)最大为多少?

 注意事项
x[i], y[i] 代表第 i 条边的两个结点,cost[i] 代表第 i 条边的花费,profit[i] 代表编号为 i 的结点的收益
1 <= x[i], y[i] <= 10^5
1 <= cost[i], profit[i] <= 100

样例
给出 x = [0,0,0],y = [1,2,3], cost = [1,1,1], profit = [1,1,2,3],返回3。

路线:0→3

给出 x = [0,0],y = [1,2], cost =[1,2], profit = [1,2,5],返回4。

路线:0→2

思路
构建数组存放树的父子关系,结点的得分,以及每条边的花费。
利用深度优先的思想,得到每个结点的得分,并求出符合条件的最大值。

#ifndef C953_H
#define C953_H
#include<iostream>
#include<vector>
#include<map>
using namespace std;
class Solution {
public:
    /**
    * @param x: The vertex of edge
    * @param y: The another vertex of edge
    * @param cost: The cost of edge
    * @param profit: The profit of vertex
    * @return: Return the max score
    */
    int getMaxScore(vector<int> &x, vector<int> &y, vector<int> &cost, vector<int> &profit) {
        // Write your code here
        int n = x.size() + 1;
        vector<int> nums(n, INT_MIN);//存放结点的得分
        nums[0] = profit[0];
        vector<vector<int>> tree(n);//存放结点及其子树
        map<pair<int, int>, int> m;//存放每条边的花费
        int res = INT_MIN;
        //以x[i]为父结点,y[i]为子结点构建其关系
        for (int i = 0; i < x.size(); ++i)
        {
            tree[x[i]].push_back(y[i]);
        }
        //用父子关系表示每一条边,并存储其花费
        for (int i = 0; i < x.size(); ++i)
        {
            m[make_pair(x[i], y[i])] = cost[i];
        }
        //深度优先,得到每个结点的得分
        for (int j = 0; j < n; ++j)
        {
            if (!tree[j].empty())
            {
                int size = tree[j].size();
                for (int k = 0; k < size; ++k)
                {
                    nums[tree[j][k]] = nums[j] + profit[tree[j][k]] - m[make_pair(j, tree[j][k])];
                }
            }
        }
        //在叶子节点中找到最大值
        for (int j = 0; j < n; ++j)
        {
            if (tree[j].empty() && res < nums[j])
            {
                res = nums[j];
            }
        }
        return res;
    }
};
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值