[BZOJ1912][Apio2010]patrol 巡逻(树上最长链)

树上最长链 树上最长链 给定一棵树,每条边有权值,计算一条最长链,时间复杂度为O(n) 设f[i]表示以i为根的子树的最长链,显然f[i]=max(f[i],f[j])其中j是i的子节点,但是这样就值考虑了不经过i的路径,也就是不包括i 要想考虑经过i的路径,就需要选择两个子节点(随便在图上画画就能知道) 把两个子节点往下走的最长路相加,再加它们到i的路径和,去更新f[i] 定义g[i]表示i往下走最远能走多少 g[i]=max(g[i],g[j]+w[i][j])其中j是i的子节点 叶子节点f=g=0 void df 阅读详情

=== ===

这里放传送门

=== ===

题解

因为一开始的图是一棵树,所以在不加边的情况下每条边一定会被经过两次,巡逻的代价固定为 ans=2∗(n−1)  。如果在树上加一条边,那么就会有一条链不需要走两次,这条链的起点和终点就是新边的起点和终点。那么如果只能在树上加一条边的话,和这条边构成环的链一定是越长越好。于是找树上最长链就能解决问题。
第一次求最长链的时候可以用dfs也可以DP,这里用了dfs,方法是先从任意一个点dfs找到最远的那个点,再从这个点dfs第二遍,找到另一个最远点,这两个点中间的那条链就是最长的,代价就变为 ans−len+1  , len  为链的长度。
可是当k=2的时候怎么办呢?题目中要求每条边必须经过一次,也就是说为了满足这个要求,上一次加边后本来可以只被经过一次的某些边可能被”强行“经过两次,也就是说这条链形成的环如果与第一次找到的链有重叠,那么这条重叠的边仍然需要走两遍,相当于没有加也没有减。那么就把上一次选定的链上的每条边边权都赋值为-1,再跑一边最长链就可以了。而这就出现了一个问题就是dfs不适用了,因为出现了负边权。于是这时使用了树形dp,用 f  数组和g 数组分别存储以结点i开头的最长链和次长链,这两个的和就是经过节点i的最长链。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k,tot,p[100010],a[200010],w[200010],next[200010],lc,ld,pre[100010],ans,st;
int wer,f[100010],g[100010];
void add(int x,int y,int v){
    a[tot]=y;w[tot]=v;next[tot]=p[x];p[x]=tot++;
}
void dfs(int u,int last,int len){
    for (int i=p[u];i!=-1;i=next[i])
      if (a[i]!=last){
          if (len+w[i]>ld){
              ld=len+w[i];lc=a[i];
          }//找到最长链
          pre[a[i]]=i;
          dfs(a[i],u,len+w[i]);
      }
}
void dp(int u,int last){
    for (int i=p[u];i!=-1;i=next[i])
      if (a[i]!=last){
          int v1,v2;
          dp(a[i],u);
          v1=f[a[i]]+w[i];
          if (v1>f[u]){//判断这个子树的答案应该更新f还是更新g,只能更新一个
              g[u]=f[u];f[u]=v1;
          }else g[u]=max(g[u],v1);
      }
      wer=max(wer,f[u]+g[u]);
}
int main()
{
    memset(p,-1,sizeof(p));
    scanf("%d%d",&n,&k);
    for (int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v,1);add(v,u,1);
    }
    ans=2*(n-1);
    dfs(1,0,0);
    memset(pre,0,sizeof(pre));
    ld=0;st=lc;dfs(st,0,0);//两次dfs,第一次的pre数组没有什么意义
    ans=ans-ld+1;
    if (k==2){
        for (int i=lc;i!=st;i=a[pre[i]^1])
          w[pre[i]]=w[pre[i]^1]=-1;//修改最长链上的边权
        wer=-0x7fffffff;dp(1,0);
        ans=ans-wer+1;
    }
    printf("%d\n",ans);
    return 0;
}

偏偏在最后出现的补充说明

DP的时候注意最长链和次长链不能在同一棵子树上。所以一棵子树的答案对于父节点来说要么更新 f  ,要么更新g 。为了在第二次求最长链时修改树上的边权,第一次求最长链的时候要顺便记录路径,即代码中的 pre  数组。

Unreal5从入门到精通之如何录制360°VR全景视频 摘要:本文详细介绍了使用虚幻引擎(UE)生成360°全景视频的完整流程。首先需启用MovieRender Queue和Panoramic Capture插件,准备场景并设置相机序列。通过影片渲染队列选择8K分辨率输出PNG序列帧,利用ffmpeg工具转换为MP4格式,最终获得高精度全景视频。该方法适用于VR内容开发,能以较低性能消耗实现影院级画质,特别适合冥想类应用场景。教程涵盖从插件配置到后期合成的全链路操作,为开发者提供高效的全景内容生产解决方案。(150字) 阅读详情

相关推荐

DeepSeek-V4 本地部署实战指南:4套方案从入门到企业级(附RTX 5090实测数据)

V4-Flash 便宜是便宜,输入 1 元/M token,输出 2 元/M token,但量大了还是肉疼。V4-Pro 更离谱,输入 12 元/M token,输出 24 元/M token,这价格要是天天调用,月账单轻松破万。用 4-bit 量化跑 V4-Flash,显存占用 ~22GB,延迟 ~80ms/token,并发能到 2-3 路。换句话说,同样的硬件,能跑更长的上下文、更大的并发。Flash 是「小而美」,一张 RTX 4090/5090 就能跑,门槛低,效果够用。

datayx的文章 9854

树上最长链 (树形dp 或 两次dfs )

带权树上最长链 (可能负权 ) 最长链:(树上直径,树上两点距离最大值,树上距离最远的两点 )。 最长链 = 以某一结点为端点的最长链+次长链。 mx1: 以 i 节点为根的子树中,i 节点到叶子节点的最长距离(不含 i 节点)即最长链 mx2: 以 i 节点为根的子树中,i 节点到叶子节点的次长距离(不含 i 节点)即次长链 #define first f #define second s #define ll long long #define pb push_back #define pii pair

qhq889的博客 1308

运算放大器 VS 仪表放大器

运算放大器(Operational Amplifier, 简称 Op Amp)和仪表放大器(Instrumentation Amplifier, 简称INA)在电子电路设计中都有非常广泛的应用,但两者在结构、特性以及应用场景上都有明显的区别。以下是它们之间主要的差异:运算放大器(Op Amp)仪表放大器(INA)运算放大器仪表放大器运算放大器仪表放大器运算放大器仪表放大器运算放大器仪表放大器总之,运算放大器是通用型放大元件,需要设计者自己做额外的电路配置;而仪表放大器则是针对高精度测量差分信号而生,内部匹配

chinahongjiang的博客 1347

树的最长路径

树的最长路径 题目描述 样例解释 前置知识 树的直径,又称树的最长链,定义为一棵树上最远的两个节点的路径,即树上一条不重复经过某一条边的最长的路径。树的直径也可以代指这条路径的长度。 求树的直径有两种比较常用的方法:树形DP和搜索。 如何找树的直径呢? 任取一点作为起点,找到距离该点最远的一个点u。 这一步可以用DFS或者BFS来解决。 再找到距离点u最远的一个点v。这一步可以用DFS或者BFS来解决。 那么点u到点v之间的路径就是一条直径了。 如何证明点u到点v之间的路径就是一条直径了呢? 要

qq_45832461的博客 4806

RV1126开发板性能实测:网络、温度与功耗全解析

本文对RV1126开发板进行了全面的性能实测,重点分析了网络性能、温度表现与功耗特性。测试发现UDP带宽可达500Mbps,但TCP性能受限于协议栈;散热设计对持续性能至关重要,大板子在AI推理和视频推流中表现更稳定。为嵌入式开发者提供了真实的选型参考和优化建议。

d3e4f的博客 267

【笔记整理】轻量级神经网络 MobileNetV3

【笔记整理】轻量级神经网络 MobileNetV3

qq_33934427的博客 4274

树的最长链

最长链,就是最长的一条路径 1 / \ \ 2 3 4 / \ \ 5 6 7 ==\ ...

weixin_30407613的博客 524

【软考】系统集成项目管理工程师(一)信息化知识

软考中级——系统集成项目管理工程师备考干货第一章:信息化知识。

商务合作 | 共同学习 | 携手共进 9万+

【bzoj1912】[Apio2010]patrol 巡逻(树上最长链)

有些东西并不是越浓越好,要恰到好处。深深的话我们浅浅地说,长长的路我们慢慢地走。——毕淑敏

薇小薇 435

Oracle EBS Tax 四国实现详解:印度、巴西、美国、阿根廷

印度:务必启用India Localization模块,不要尝试用标准EBTax模拟GST逻辑 巴西:必须配置NF-e接口,建议聘请本地税务顾问设置CFOP和NCM代码映射 美国:跨州业务强烈建议购买Vertex或Avalara服务,自建税率表维护成本极高 阿根廷:注意1:1:1架构限制,提前规划Legal Entity和OU结构

金牌架构师 260

RuoYi-Cloud-Plus使用minio进行文件上传图片后无法预览解决_修改minio配置minio桶权限---SpringCloud工作笔记198

在文件管理的位置,发现刚刚上传的图片文件,会显示 预览图片失败 后来经过多方查看,发现是minio的配置的问题。可以看到首先登录RuoYi-Cloud-Plus系统然后,打开文件管理页面可以看到,当上传了图片文件以后。登录以后,选中左侧Buckets,可以看到有自己用的桶,找到以后点击打开。显示文件展示中,文件预览失败,那么这个时候,去修改minio的配置。可以看到,点击配置管理,这里我们启用的是minio对吧。默认是没有配置的这个时候,是允许下载,但不允许预览的.

添柴程序猿的专栏 5568

bzoj1912 [Apio2010]patrol 巡逻(dp求树上最长链)

显然答案一开始是n-1<<1,每条边都要走两遍。 如果K=1,可以新建一条道路,那么应该把树上最长链的两端连起来,这样就不用走两遍树上最长链了,而是只需要走一遍,(通过新边直接过去,不需要再返回了)。因此答案就是减去树上最长链+1。 如果K=2,还可以再新建一条,那么我们发现如果这次选择的链和上次选择的最长链有交集,则这一部分的边还是要走两遍,因此我们把最长链上的边权均变为-1,再求树上最长链,

Icefox的博客 579

05 - GRACE数据处理-球谐展开与球谐综合

GRACE数据处理-球谐展开和综合前面在介绍GRACE相关理论的时候提到过下面的公式,从公式形式上可以看出,面密度变化和球谐系数(CS)之间是能够相互转换的,那这个转化的过程可以称为球谐展开,简单理解就是将全球网格数据转化为球谐系数的过程。而球谐综合可以看作是球谐展开的逆过程,利用球谐系数计算到全球格网分布。

weixin_43339605的博客 1050

bzoj 1912: [Apio2010]patrol 巡逻

Description solution 正解:贪心+DP 首先对于K=1的情况我们可以发现答案是 \((n-1)*2\)-树的直径+1 K=2同理,我们也要再找出一条不相交的树的直径,然后怎么保证不相交呢? 其实只需要把第一次求得的直径上的点赋值为-1即可 如果一条边再两次都出现,就相互抵消了,去掉抵消的部分,就完美的形成了不相交的两条链了,非常巧妙 另外,两遍dfs求直径的方法在有...

baicu9711的博客 138

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

[BZOJ1912][Apio2010]patrol 巡逻(dfs+并查集+树形dp)

痛苦的事是不用一直去想的,因为是想忘也忘不掉的。

zyf2000 1005

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

bzoj1912 [Apio2010]patrol 巡逻

http://www.elijahqi.win/2018/03/06/bzoj1912/ 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, …, n。有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到达其 他任一个村庄。每条道路的长度均为 1 个单位。 为保证该地区的安全,巡警车每天要到所有的道路上巡逻。警察局设在编号 为 1 的村...

Elijahqi 265

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

BZOJ 1912:[Apio2010]patrol 巡逻(树直径)

1912: [Apio2010]patrol 巡逻 Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2)。接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n)。 Output 输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离。 Sample Input 8 1 1 2 3 1 3 4 ...

weixin_33725515的博客 139

BZOJ1912[Apio2010]patrol 巡逻

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1912 题解:嗯,这是一道很好的题。 转自:http://www.cnblogs.com/iwtwiioi/p/4126284.html   对于 k==0 的情况:   我们发现遍历一棵树最后回到原点,那么对于所有的边,我们都是走过去,再走回来。   答案 (n−11)   对于 k

ACist的博客 404

【树形dp 最长链】bzoj1912: [Apio2010]patrol 巡逻

富有思维性的树形dp Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2)。接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n)。 Output 输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离。 Sample Input 8 1 1 2 3 1 3 4 5 3 ...

weixin_30667301的博客 140

bzoj1912: [Apio2010]patrol 巡逻

传送门 k=0显然每条边都要走两次,答案=(n-1)*2 k=1我们找到树上最长链,在两段连边 在环上的就不用再走一遍了 答案=(n-1)-链长+1 k=2在k=1的基础上将那些边编圈变为-1,再跑最长链 不再环上显然只要一遍 但是在两个环上要走两遍。 答案=(n-1)-链长1+1-链长2+1#include<iostream> #incl

zyy大蒟蒻的博客 335

bzoj1912 [Apio2010]patrol 巡逻(树的直径[变式])

Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2)。接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n)。Output 输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离。Sample Input 8 1 1 2 3 1 3 4 5 3 7 5 8 5 5 6 Sampl

Coco_T的博客 510

【bzoj1912】 Apio2010—patrol 巡逻

http://www.lydsy.com/JudgeOnline/problem.php?id=1912(题目链接) 题意   给出一棵树,要求在树上添加K(1 or 2)条边,添加的边必须经过一次,使得从1号节点到达每个节点最后返回1号节点所经过的路径最短。 Solution   如果不添加边,那么答案一定是每条边经过两次。   如果K为1,那么答案就很明显对吧,找到树的直径,链接直...

weixin_30342827的博客 96
上一篇: [BZOJ1189][HNOI2007]紧急疏散evacuate(二分+网络流)
下一篇: [BZOJ2811][Apio2012]Guard(线段树+二分+贪心)
FromATP
博客等级 码龄10年 75粉丝 163原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值