leetcode每日一题(好几天之前的) -- 3068.最大节点价值之和

思路

一开始,我是想利用异或的特性,重复异或两次变为原值,那么只要异或后的值更大,就更新

  • 但是这和题意相违背,因为题目做处理是对边整体进行的 (我写的版本是对顶点分别控制的)

但即使加上一起变动的特性,这个思路也是不对的

  • 如果一个顶点有多条边相连 & 当前已经对先遍历到的边异或过
  • 那么到了同顶点的其他边时就无法再变动了 -- 因为异或后会变小(变为原值),但是可能这里对另一个顶点异或后会带来全局的更优解

总之还是去看了题解

贪心

梳理一下题意

  • 规定是可以对相邻两个节点同时进行异或操作,但是树中任意两个节点之间都是可以联通的(树 -- 无环且连通的无向图)
  • 所以如果对一条路径上的所有边都进行异或操作,最终只有路径端点被异或,其他节点都没变(异或两次恢复了)
  • 于是,原先的 只有相邻节点可以被异或 可以转换成 对任意两个节点异或

于是,可以先对每个节点进行异或,计算出和原来相比的差值

  • 如果差值为正,说明异或后可以使总和变大,那么就加入到结果中
  • 既然要求和的最大值 & 可以对任意两点进行异或,那就直接按差值排序 ,然后再成对使用

树形dp

递归

本题中,每个节点有两种选择:异或该节点 / 不异或该节点

  • 而这里的选择取决于该节点的子节点选择了什么,子节点的选择又取决于孙子节点...
  • 于是形成了自顶向下的依赖关系,所以最好是使用递归逻辑

预处理

将原先给定边的形式,转换为邻接表

  • 方便后续的递归操作(dfs)

未完待续....

代码

cpp 复制代码
class Solution {
public:
    long long maximumValueSum(vector<int>& nums, int k,
                              vector<vector<int>>& edges) {
        long long res = accumulate(nums.begin(), nums.end(), 0ll);
        vector<int> diff;
        for (auto& a : nums) {
            diff.push_back((a ^ k) - a);
        }
        sort(diff.begin(), diff.end());
        for (int i = diff.size() - 1; i > 0 && diff[i] + diff[i - 1] >= 0;
             i -= 2) {
            res += max(0, diff[i] + diff[i - 1]);
        }
        return res;
    }
};
cpp 复制代码
class Solution {
    // dfs函数返回一个pair<long long, long long>:
    // first  -> 当前节点u"不进行异或操作"时,子树的最大价值和
    // second -> 当前节点u"进行异或操作"时,子树的最大价值和
    pair<long long, long long> dfs(int node, int parent,
                                   const vector<vector<int>>& graph,
                                   const vector<int>& nums, int k) {
        long long sumIfNotXor = 0;
        long long sumIfXor = LLONG_MIN;

        for (int child : graph[node]) {
            //
            if (child == parent)
                continue;
            auto [childNotXor, childXor] = dfs(child, node, graph, nums, k);

            long long newSumIfXor =
                max(sumIfXor + childNotXor, sumIfNotXor + childXor);
            long long newSumIfNotXor =
                max(sumIfNotXor + childNotXor, sumIfXor + childXor);

            sumIfXor = newSumIfXor;
            sumIfNotXor = newSumIfNotXor;
        }

        long long resultNotXor =
            max(sumIfNotXor + nums[node], sumIfXor + (nums[node] ^ k));
        long long resultXor =
            max(sumIfXor + nums[node], sumIfNotXor + (nums[node] ^ k));

        return {resultNotXor, resultXor};
    }

public:
    long long maximumValueSum(vector<int>& nums, int k,
                              vector<vector<int>>& edges) {
        int n = (int)nums.size();
        vector<vector<int>> graph(n);
        // 建图,邻接表形式
        for (auto& edge : edges) {
            int u = edge[0], v = edge[1];
            graph[u].push_back(v);
            graph[v].push_back(u);
        }

        // 从根节点0开始DFS,返回两个状态的最大值,我们要的是未异或状态的最大值
        return dfs(0, -1, graph, nums, k).first;
    }
};
相关推荐
罗西的思考19 分钟前
【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (4)--- 系统架构
人工智能·算法·机器学习
QiLinkOS21 分钟前
从技术到资产的跃迁:企业专利布局的深层逻辑
c语言·数据结构·c++·单片机·嵌入式硬件·算法·开源
aini_lovee28 分钟前
FMCW雷达测速测距系统(锯齿波 + CFAR检测)
算法
qq_2975746731 分钟前
设计模式系列文章(基础篇第 11 篇):模板方法模式——定义算法骨架,实现代码复用与流程统一
算法·设计模式·模板方法模式
lqqjuly38 分钟前
知识蒸馏:理论、算法与可运行实现
人工智能·深度学习·算法
水上冰石1 小时前
comfui的sd1.5模型,有多少采样算法,详解每一个采样算法
人工智能·算法
黎阳之光1 小时前
视频孪生+空天地水工融合,黎阳之光构建智慧水利监测新范式
大数据·人工智能·物联网·算法·安全
cheems95271 小时前
[算法手记] 贪心 爬楼梯问题
算法·贪心算法
KaMeidebaby1 小时前
卡梅德生物技术快报|酵母双杂交 cDNA 文库构建与蛋白互作筛选流程
服务器·前端·数据库·人工智能·算法
圣保罗的大教堂2 小时前
leetcode 3300. 替换为数位和以后的最小元素 简单
leetcode