P3647 题解

news2025/1/19 2:41:18

文章目录

  • P3647 题解
    • Overview
    • Description
    • Solution
      • Lemma
        • Proof
      • Main
    • Code

P3647 题解

Overview

很好的题,但是难度较大。

模拟小数据!——【数据删除】

Description

给定一颗树,有边权,已知这棵树是由这两个操作得到的:

  • Append(u, w):在 u u u w w w 之间连一条红边,注意这里的 w w w 必须是新点
  • Insert(u, v, w):在 u u u w w w v v v w w w 之间各连一条蓝边,注意这里的 w w w 必须是新点

问蓝线的长度最大能到多少。

Solution

我们可以尝试将所有的 Insert 所产生的蓝边对都提取出来。
它们只可能有两种形式:son - u - fatherson1 - u - son2

Lemma

引理:所有的蓝边都可以在某一个根上表现出形如 son - u - father 的形式。

Proof

当树上没有形如 son1 - u - son2 的蓝边时,显然成立;

当树上恰好有一个形如 son1 - u - son2 的蓝边时,可以将 son1son2 其中之一作为根,解决问题;

当树上有大于一个形如 son1 - u - son2 的蓝边时,可以证明不存在这样的边。
如图,当存在形如 1 的情况时,son1son2 构成了单独的连通块,因为如果不是,那么 son1son2 一定会是父子关系,矛盾;
当存在多个这样的连通块时,如图 2,建树时节点一定会组成单一的连通块,因为 u u u 总是存在,所以不成立。
only one component can exist

Main

有了引理,就可以树形 dp 了。

枚举树根,对每个根 DP。设 d u , 0 / 1 d_{u,0/1} du,0/1 u u u 为根, u u u 是否为蓝边终点的子树最大边权和。

先看 d u , 0 d_{u,0} du,0,因为没有边上的限制,所以可以任意取,对于是中点的情况,可以再加上边权 w ( u , v ) w(u,v) w(u,v),即 max ⁡ ( d v , 1 + w ( u , v ) , d v , 0 ) \max(d_{v,1}+w(u,v), d_{v,0}) max(dv,1+w(u,v),dv,0)
再看 d u , 1 d_{u,1} du,1,一定有一个 d v , 0 + w ( u , v ) d_{v,0}+w(u,v) dv,0+w(u,v),其它都是 max ⁡ ( d v , 1 + w ( u , v ) , d v , 0 ) \max(d_{v,1}+w(u,v), d_{v,0}) max(dv,1+w(u,v),dv,0),所以要加上 max ⁡ Δ sum \max \Delta_{\text{sum}} maxΔsum

所以关于 d d d 的状态转移方程可以这样写:

d u , 0 = ∑ v ∈ son ( u ) max ⁡ ( d v , 1 + w ( u , v ) , d v , 0 ) d u , 1 = d u , 0 + max ⁡ v ∈ son ( u ) { d v , 0 + w ( u , v ) − max ⁡ ( d v , 1 + w ( u , v ) , d v , 0 ) } d_{u,0} = \sum_{v\in \text{son}(u)}\max(d_{v,1}+w(u,v),d_{v,0})\\d_{u,1} = d_{u,0}+\max_{v\in \text{son}(u)}\{d_{v,0} + w(u,v) - \max(d_{v,1} + w(u,v), d_{v,0})\} du,0=vson(u)max(dv,1+w(u,v),dv,0)du,1=du,0+vson(u)max{dv,0+w(u,v)max(dv,1+w(u,v),dv,0)}

这样,就可以枚举根得到 O ( n 2 ) O(n^2) O(n2) 的复杂度, 15 pts 15\text{pts} 15pts

接下来考虑换根 DP。

一张图解释接下来两个 DP 数组的含义。

g is the ans k is the curr_up
这里的 g g g 并不描述这个子树,而是以 u u u 为根的整棵树

根据 f f f 的转移方程,我们照样也可以推出 g g g k k k 的转移方程,留给读者思考。

注意到方程里仍有大量之前可以利用的内容,所以需要维护最大值和次大值。

Code

#include <bits/stdc++.h>

using namespace std;

int dp[200001][2], dp1[200001][2], dp2[200001][2], mx[200001], mx2[200001];

vector<pair<int, int> > gv[200001];

inline void add_edge(int u, int v, int w){
	gv[u].push_back(make_pair(v, w));
	gv[v].push_back(make_pair(u, w));
}

void dfs(int u, int fa){
	vector<int> vec;
	vec.push_back(INT_MIN), vec.push_back(INT_MIN);
	for(auto v : gv[u]){
		if(v.first == fa) continue;
		dfs(v.first, u);
		dp[u][0] += max(dp[v.first][0], dp[v.first][1] + v.second);
		vec.push_back(dp[v.first][0] + v.second - max(dp[v.first][0], dp[v.first][1] + v.second));
	}
	sort(vec.begin(), vec.end(), greater<int>());
	mx[u] = vec[0], mx2[u] = vec[1];
	dp[u][1] = dp[u][0] + mx[u];
}


void dfs1(int u, int fa, int lst){
	for(auto v : gv[u]){
		if(v.first == fa) continue;
		int tmp = dp[v.first][0] + v.second - max(dp[v.first][0], dp[v.first][1] + v.second);
		dp2[u][0] = dp1[u][0] - max(dp[v.first][0], dp[v.first][1] + v.second);
		dp2[u][1] = dp2[u][0] + (mx[u] == tmp ? mx2[u] : mx[u]);
		if(fa + 1) dp2[u][1] = max(dp2[u][1], dp2[u][0] + dp2[fa][0] + lst - max(dp2[fa][0], dp2[fa][1] + lst));
		dp1[v.first][0] = dp[v.first][0] + max(dp2[u][0], dp2[u][1] + v.second);
//		dp1[v.first][1] = dp1[v.first][0] + max(mx[v.first], dp2[u][0] + v.second - max(dp2[u][0], dp2[u][1] + v.second));
		dfs1(v.first, u, v.second);
	}
}

void init_vars(){
	// type your initiating code...
}

void solve(int testcase, ...){
	init_vars();
	int n; cin >> n;
	for(int i = 0; i < n - 1; i++){
		int u, v, w; cin >> u >> v >> w;
		add_edge(u, v, w);
	}
	dfs(1, -1); dp1[1][0] = dp[1][0];
	dfs1(1, -1, 0);
	int ans = 0;
	for(int i = 1; i <= n; i++){
		//cout << mx[i] << " " << mx2[i] << endl;
		ans = max(ans, dp1[i][0]);
	}
	cout << ans << endl;
}

signed main(){
#ifdef files
	freopen(".in", "r", stdin);
	freopen(".out", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	solve(1);
#ifdef files
	fclose(stdin); fclose(stdout);
#endif
	return 0;
}

/*
 *  things to check
 *  1.  int overflow or long long memory need
 *  2.  recursion/array/binary search/dp/loop bounds
 *  3.  precision
 *  4.  special cases(n=1,bounds)
 *  5.  delete debug statements
 *  6.  initialize(especially multi-tests)
 *  7.  = or == , n or m ,++ or -- , i or j , > or >= , < or <=
 *  8.  keep it simple and stupid
 *  9.  do not delete, use // instead
 *  10. operator priority
 *  11. is there anything extra to output?
 *  12. THINK TWICE CODE ONCE, THINK ONCE DEBUG FOREVER
 *  13. submit ONCE, AC once. submit twice, WA forever
 *  14. calm down and you'll get good rank
 *  15. even a bit wrong scores zero
 *  16. ...
 **/

 /*
 *  something to think about
 *  1. greedy? dp? searching? dp with matrix/ segment tree? binary search? ...?
 *  2. If it is difficult, why not the opposite?
 **/

/*
   ##########   ############   #####         #####
 ####                 #####      ####       ####
####                 #####        ####     ####
####             ##########        ####   ####
####               #####              #####
####              #####               #####
 ####            #####                #####
   ###########  #############         #####
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1441888.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hexo更换Matery主题

引言 在数字化时代&#xff0c;拥有一个个人博客已经成为许多人展示自己技能、分享知识和与世界互动的重要方式。而在众多博客平台中&#xff0c;Hexo因其简洁、高效和易于定制的特点而备受青睐。本文将详细介绍如何为你的Hexo博客更换主题&#xff0c;让你的个人博客在互联网…

LabVIEW工业监控系统

LabVIEW工业监控系统 介绍了一个基于LabVIEW软件开发的工业监控系统。系统通过虚拟测控技术和先进的数据处理能力&#xff0c;实现对工业过程的高效监控&#xff0c;提升系统的自动化和智能化水平&#xff0c;从而满足现代工业对高效率、高稳定性和低成本的需求。 随着工业自…

机器学习:回归决策树(Python)

一、平方误差的计算 square_error_utils.py import numpy as npclass SquareErrorUtils:"""平方误差最小化准则&#xff0c;选择其中最优的一个作为切分点对特征属性进行分箱处理"""staticmethoddef _set_sample_weight(sample_weight, n_samp…

Flask基础学习

1.debug、host、port 模式修改 1) debug模式 默认debug模式是off&#xff0c;在修改代码调试过程中需要暂停重启使用&#xff0c;这时可修改on模式解决。 同时在debug模式开启下可看到出错信息。 下面有关于Pycharm社区版和专业版修改debug模式的区别 专业版 社区版&#…

3.1 Verilog 连续赋值

关键词&#xff1a;assign&#xff0c; 全加器 连续赋值语句是 Verilog 数据流建模的基本语句&#xff0c;用于对 wire 型变量进行赋值。&#xff1a; 格式如下 assign LHS_target RHS_expression &#xff1b; LHS&#xff08;left hand side&#xff09; 指赋值操作…

Go语言每日一题——链表篇(七)

传送门 牛客面试笔试必刷101题 ----------------删除链表的倒数第n个节点 题目以及解析 题目 解题代码及解析 解析 这一道题与昨天的题目在解题思路上有一定的相似之处&#xff0c;都是基于双指针定义快慢指针&#xff0c;这里我们让快指针先走n步&#xff0c;又因为n一定…

[Angular 基础] - 自定义事件 自定义属性

[Angular 基础] - 自定义事件 & 自定义属性 之前的笔记&#xff1a; [Angular 基础] - Angular 渲染过程 & 组件的创建 [Angular 基础] - 数据绑定(databinding) [Angular 基础] - 指令(directives) 以上是能够实现渲染静态页面的基础 之前的内容主要学习了怎么通过…

C语言-3

定义指针 /*指针的概念:1.为了方便访问内存中的内容&#xff0c;给每一个内存单元&#xff0c;进行编号&#xff0c;那么我们称这个编号为地址&#xff0c;也就是指针。2.指针也是一种数据类型&#xff0c;指针变量有自己的内存&#xff0c;里面存储的是地址&#xff0c;也就是…

VMware17上安装centos7.9

一、下载安装包&#xff1a; 1、VMware安装 VMware 下载地址&#xff1a; https://www.vmware.com/cn/products/workstation-pro.html VMware下载后安装即可 安装教程可以参考VMware安装教程 2、CentOs7.9下载地址&#xff1a; http://mirrors.aliyun.com/centos/7.9.2009/iso…

HTML+CSS:全景轮播

效果演示 实现了一个简单的网页布局&#xff0c;其中包含了五个不同的盒子&#xff0c;每个盒子都有一个不同的背景图片&#xff0c;并且它们之间有一些间距。当鼠标悬停在某个盒子上时&#xff0c;它的背景图片会变暗&#xff0c;并且文字会变成白色。这些盒子和按钮都被放在一…

如何用Hexo搭建一个优雅的博客

引言 在数字化时代&#xff0c;拥有一个个人博客已经成为许多人展示自己技能、分享知识和与世界互动的重要方式。而在众多博客平台中&#xff0c;Hexo因其简洁、高效和易于定制的特点而备受青睐。本文将详细介绍如何从零开始搭建一个Hexo博客&#xff0c;让你的个人博客在互联…

Git版本与分支

目录 一、Git 二、配置SSH 1.什么是SSH Key 2.配置SSH Key 三、分支 1.为什么要使用分支 2.四个环境及特点 3.实践操作 1.创建分支 2.查看分支 3.切换分支 4.合并分支 5.删除分支 6.重命名分支 7.推送远程分支 8.拉取远程分支 9.克隆指定分支 四、版本 1.什…

Linux操作系统基础(三):虚拟机与Linux系统安装

文章目录 虚拟机与Linux系统安装 一、系统的安装方式 二、虚拟机概念 三、虚拟机的安装 四、Linux系统安装 1、解压人工智能虚拟机 2、找到解压目录中的node1.vmx 3、启动操作系统 虚拟机与Linux系统安装 一、系统的安装方式 Linux操作系统也有两种安装方式&#xf…

蓝桥杯每日一题------背包问题(一)

背包问题 阅读小提示&#xff1a;这篇文章稍微有点长&#xff0c;希望可以对背包问题进行系统详细的讲解&#xff0c;在看的过程中如果有任何疑问请在评论区里指出。因为篇幅过长也可以进行选择性阅读&#xff0c;读取自己想要的那一部分即可。 前言 背包问题可以看作动态规…

js手写Promise(上)

目录 构造函数resolve与reject状态改变状态改变后就无法再次改变 代码优化回调函数中抛出错误 thenonFulfilled和onRejected的调用时机异步then多个then 如果是不知道或者对Promise不熟悉的铁铁可以先看我这篇文章 Promise 构造函数 在最开始&#xff0c;我们先不去考虑Promi…

精简还是全能?如何在 Full 和 Lite 之间做出最佳选择!关于Configuration注解的Full模式与Lite模式(SpringBoot2)

&#x1f3c3;‍♂️ 微信公众号: 朕在debugger© 版权: 本文由【朕在debugger】原创、需要转载请联系博主&#x1f4d5; 如果文章对您有所帮助&#xff0c;欢迎关注、点赞、转发和订阅专栏&#xff01; 前言 关于 Configuration 注解&#xff0c;相信在座的各位 Javaer 都…

可达鸭二月月赛——基础赛第六场(周五)题解,这次四个题的题解都在这一篇文章内,满满干货,含有位运算的详细用法介绍。

姓名 王胤皓 T1 题解 T1 题面 T1 思路 样例输入就是骗人的&#xff0c;其实直接输出就可以了&#xff0c;输出 Hello 2024&#xff0c;注意&#xff0c;中间有一个空格&#xff01; T1 代码 #include<bits/stdc.h> using namespace std; #define ll long long int …

Swift 使用 Combine 管道和线程进行开发 从入门到精通八

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三Swift Combine 发布者publisher的生命周期 从入门到精通四Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五Swift Com…

ANSI Escape Sequence 下落的方块

ANSI Escape Sequence 下落的方块 1. ANSI Escape 的用途 无意中发现 B站有人讲解&#xff0c; 完全基于终端实现俄罗斯方块。 基本想法是借助于 ANSI Escape Sequence 实现方方块的绘制、 下落动态效果等。对于只了解 ansi escape sequence 用于 log 的颜色打印的人来说&…

(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第10章 项目进度管理(四)

博主2023年11月通过了信息系统项目管理的考试&#xff0c;考试过程中发现考试的内容全部是教材中的内容&#xff0c;非常符合我学习的思路&#xff0c;因此博主想通过该平台把自己学习过程中的经验和教材博主认为重要的知识点分享给大家&#xff0c;希望更多的人能够通过考试&a…