[题解]P3629 [APIO2010] 巡逻
\(k=1\)时,我们一定贪心选择直径\(d\)的两个端点建立道路,所以答案是\(2\times(n-1)-d+1\)。
\(k=2\)时,两条新建的道路恰好形成\(2\)个环,我们通过手玩可以发现一个结论:
- \(1\)条边恰好被经过\(1\)次,当且仅当它恰好位于\(1\)个环上。
- \(1\)条边恰好被经过\(2\)次,当且仅当它不满足上面的条件。
可以结合下图理解。

那么我们的策略就是尽可能最大化“恰好位于\(1\)个环上”的边数。
可以证明,\(k=2\)时选择直径的两个端点修路一定可以取到最优解。
我们假设\(AB\)、\(CD\)是我们选取的两条路径,而\(EF\)是直径。我们证明,对于\(AB,CD\)的所有选法,改为让\(EF\)参与一定不会让答案更劣。
- 当\(AB,CD\)没有公共边时,直接用\(EF\)代替其中一条路径即可,没有讨论的必要。
- 当\(AB,CD\)有公共边时,这一段公共部分一定是连续的(否则就有环了),将其设为\(PQ\),讨论\(EF\)的位置:
- 当\(EF\)与\(PQ\)无公共边时,如下图,选\(AB,CD\)可以用选\(FB,ED\)代替(因为\(FY\ge AY,EX\ge CX\)),而选\(FB,ED\iff\)选\(EF,BD\)。
- 当\(EF\)与\(PQ\)的一部分重合时,如下图(\(EF\)只与\(PQ\)有重合的情况没画,是同理的),\(EF\)可以代替掉\(AB,CD\)的任意一条,因为它的重合长度更短,且自身更长。
- 当\(EF\)覆盖\(PQ\)时,如下图,我们可以将选\(AB,CD\)看作选\(AD,BC\),而\(AD,BC\)可以用选\(EF,BC\)代替,因为两种选法重合部分长度相同,而\(EF\ge AD\)。根据\(EF\)覆盖的位置,这里的情况会有所不同,但是证明同理。
(其实就是感性理解啦……)
有了这个结论,我们第一条路径就可以大胆选择直径\(d\)。接下来我们考虑另一条路径\(d'\)怎么找,才能让答案最大。
我们知道\(d'\)与\(d\)每有一条边重合,答案都相较\(2\times(n-1)-d+1\)增加了\(1\);每有一条边不重合,答案都相较\(2\times(n-1)-d+1\)减少了\(1\)。
所以我们可以先跑一遍直径\(d\),然后把直径上的边权值都设为\(-1\),再跑一遍直径\(d'\),答案即为\(2\times(n-1)-d-d'+2\)。
第\(1\)次求直径无负权边,且需要记录路径,所以使用两次DFS;第\(2\)次有负权边,不需要记录路径,所以使用树形DP。
时间复杂度\(O(n)\)。
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 100010
using namespace std;
int n,k,d[N],cur,pre[N],f[N],dis;
bool flg;
bitset<N> vis;
vector<int> G[N];
void dfs(int u,int fa){
for(int i:G[u]){
if(i==fa) continue;
d[i]=d[u]+1;
if(d[i]>d[cur]) cur=i;
dfs(i,u);
}
if(flg) pre[u]=fa;
}
void dfs2(int u,int fa){
for(int i:G[u]){
if(i==fa) continue;
int w=(vis[u]&&vis[i]?-1:1);
dfs2(i,u);
dis=max(dis,f[u]+f[i]+w);
f[u]=max(f[u],f[i]+w);
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>k;
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
G[u].emplace_back(v);
G[v].emplace_back(u);
}
dfs(1,0),d[cur]=0,flg=1,dfs(cur,0);
if(k==1){
cout<<2*(n-1)-d[cur]+1<<"\n";
return 0;
}
for(int i=cur;i;i=pre[i]) vis[i]=1;
dfs2(1,0);
cout<<2*(n-1)-d[cur]-dis+2<<"\n";
return 0;
}
[题解]P3629 [APIO2010] 巡逻的更多相关文章
- 洛谷 P3629 [APIO2010]巡逻 解题报告
P3629 [APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通 ...
- [洛谷P3629] [APIO2010]巡逻
洛谷题目链接:[APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以 ...
- 题解 BZOJ 1912 && luogu P3629 [APIO2010]巡逻 (树的直径)
本来抄了篇题解,后来觉得题解都太不友好(我太菜了),一气之下自己打...一打打到第二天QAQ 首先什么边也不加时,总路程就是2*(n-1) 考虑k=1的时候,答案显然是2*(n-1)-直径+1=2*n ...
- 【题解】P3629 [APIO2010]巡逻
link 题意 有 \(n\) 个村庄,编号为 \(1, 2, ..., n\) .有 \(n – 1\) 条道路连接着这些村 庄,从任何一个村庄都可以到达其他任一个村庄.道路长度均为 1. 巡警车每 ...
- P3629 [APIO2010]巡逻
题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到达其 他任一个村庄.每条道 ...
- 洛谷 P3629 [APIO2010]巡逻
题目在这里 这是一个紫题,当然很难. 我们往简单的想,不建立新的道路时,从1号节点出发,把整棵树上的每条边遍历至少一次,再回到1号节点,会恰好经过每条边两次,路线总长度为$2(n-1)$,根据树的深度 ...
- 树的直径初探+Luogu P3629 [APIO2010]巡逻【树的直径】By cellur925
题目传送门 我们先来介绍一个概念:树的直径. 树的直径:树中最远的两个节点间的距离.(树的最长链)树的直径有两种方法,都是$O(N)$. 第一种:两遍bfs/dfs(这里写的是两遍bfs) 从任意一个 ...
- 洛谷P3629 [APIO2010]巡逻(树的直径)
如果考虑不算上新修的道路,那么答案显然为\(2*(n-1)\). 考虑\(k=1\)的情况,会发现如果我们新修建一个道路,那么就会有一段路程少走一遍.这时选择连接树的直径的两个端点显然是最优的. 难就 ...
- P3629 [APIO2010] 巡逻 (树的直径)
(这道题考察了求直径的两种方法......) 在原图中,每条边要经过两次,增加1条后,形成了一个环,那么环上的边只需要经过一次了(大量画图分析得),再增加一条又会形成一个环,如果这两个环有重叠,重叠部 ...
- [APIO2010]巡逻(树的直径)
[APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通过这些道路到 ...
随机推荐
- 启智树提高组day4T3 T3(t3.cpp,1s,512MB)
启智树提高组day4T3 T3(t3.cpp,1s,512MB) 题面描述 输入格式 输出格式 样例输入 样例输出 数据范围 题解 task1 暴力dfs 10分 Code 1 #include< ...
- VitePress 集成 Waline
转载自我的个人博客:小树 VitePress 本身基于 Vue3,可以通过组件将 Waline 集成到页面中,关于 VitePress 中的组件可以看这篇文章:组件 | VitePress 首先在 . ...
- Svelte 5 状态管理全解析:从响应式核心到项目实战
Svelte 5 的状态管理以 "编译时优化" 为核心,通过 响应式声明(Reactive Declarations) 和 状态容器(Stores) 的组合,实现了简洁高效的状态控 ...
- helm常用操作整理
说明 下面是整理的日常常用的一些helm操作,后面会持续更新 下载chart到本地 helm repo add bitnami https://charts.bitnami.com/bitnami # ...
- CRM 价格更新
FUNCTION zcrm_reprice_bt. *"------------------------------------------------------------------- ...
- HashMap集合--基本操作流程的源码可视化
本文主要包含:HashMap 插入过程.扩容过程.查询过程和删除过程的源码可视化 文章对应的视频连接:https://www.bilibili.com/video/BV1wM3KzaE3d/ 1. 操 ...
- 华为机试题 求最大连续bit数
简介 c = c++ ? c = ++c ? code #include <iostream> #include <string> using namespace std; i ...
- NBJS 笔试记录
1. 然后要知道三极管是NPN还是PNP. 一般说NPN管, 工作在放大区的时候要求,集电极反偏,发射极正偏,这要求集电极电压>基极电压>发射极电压. 也就是一楼说的Vc>Vb> ...
- 多Agent协作入门:顺序编排模式
大家好,我是Edison. 上一篇我们学习了Semantic Kernel中的并发编排模式,它非常适合并行分析.独立子任务并集成决策的任务场景.今天,我们学习新的模式:顺序编排. 顺序编排模式简介 在 ...
- 使用RestCloud ETL Shell组件实现定时调度DataX离线任务
RestCloud ETL社区版是一款数据集成工具,提供可视化多数据管道构建.数据源管理.运行监控及权限管理功能. 1.场景说明: 对于一些已经在使用阿里的离线数据同步工具DataX的用户,想实现每天 ...


