【洛谷 P3629】 [APIO2010]巡逻 (树的直径)
容易发现,当加一条边时,树上会形成一个环,这个环上的每个点都是只要走一次的,也就是说我们的答案减少了这个环上点的个数,要使答案最小,即要使环上的点最多,求出直径\(L\),则答案为\(2(n-1)-L+1\)。
当加两条边时,同样会形成一个新环,但这个新环可能和第一个环有交点,而这些交点仍是要走两次的,所以我们要让交点的个数尽可能小,所以,把原直径上的所有边权取反,代表若取了这条边,答案会增大那么多,然后再求一次树的直径\(L_1\),则答案为\(2(n-1)-L+1-L_1+1=2n-L-L_1\)。
注意,第二次求直径不能用两边\(DFS/BFS\)来求,因为树中有负权边,直接跑答案显然是错的,所以我们要用树形\(DP\)求直径。
#include <cstdio>
const int MAXN = 5000010;
namespace IO{
inline int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
}using namespace IO;
namespace G{
struct Edge{
int next, to, dis;
}e[MAXN << 1];
int head[MAXN], num;
inline void Add(int from, int to, int dis){
e[++num].to = to;
e[num].dis = dis;
e[num].next = head[from];
head[from] = num;
}
}using namespace G;
int n, k, s, t;
int a, b;
int pre[MAXN];
int Max = 0;
inline int max(int a, int b){
return a > b ? a : b;
}
void dfs(int u, int fa, int dep){
if(dep > Max && fa) s = u, Max = dep;
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
dfs(e[i].to, u, dep + e[i].dis);
}
void DFS(int u, int fa, int dep){
if(dep > Max) t = u, Max = dep;
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
pre[e[i].to] = u, DFS(e[i].to, u, dep + e[i].dis);
}
int d[MAXN], ans = -2147483647;
void dp(int u, int fa){
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa){
dp(e[i].to, u);
ans = max(ans, d[u] + d[e[i].to] + e[i].dis);
d[u] = max(d[u], d[e[i].to] + e[i].dis);
}
}
int main(){
n = read(); k = read();
for(int i = 1; i < n; ++i){
a = read(); b = read();
Add(a, b, 1); Add(b, a, 1);
}
Max = -2147483647; dfs(1, 0, 0);
Max = -2147483647; DFS(s, 0, 0);
if(k == 1){
printf("%d\n", (n << 1) - 1 - Max);
return 0;
}
int now = t;
while(now != s){
for(int i = head[now]; i; i = e[i].next)
if(e[i].to == pre[now]){
e[i].dis = -1;
break;
}
now = pre[now];
}
dp(t, 0);
printf("%d\n", (n << 1) - Max - ans);
return 0;
}
【洛谷 P3629】 [APIO2010]巡逻 (树的直径)的更多相关文章
- 洛谷 P3629 [APIO2010]巡逻 解题报告
P3629 [APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通 ...
- 洛谷P3629 [APIO2010]巡逻(树的直径)
如果考虑不算上新修的道路,那么答案显然为\(2*(n-1)\). 考虑\(k=1\)的情况,会发现如果我们新修建一个道路,那么就会有一段路程少走一遍.这时选择连接树的直径的两个端点显然是最优的. 难就 ...
- [洛谷P3629] [APIO2010]巡逻
洛谷题目链接:[APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以 ...
- 洛谷 P3629 [APIO2010]巡逻
题目在这里 这是一个紫题,当然很难. 我们往简单的想,不建立新的道路时,从1号节点出发,把整棵树上的每条边遍历至少一次,再回到1号节点,会恰好经过每条边两次,路线总长度为$2(n-1)$,根据树的深度 ...
- BZOJ1912或洛谷3629 [APIO2010]巡逻
一道树的直径 BZOJ原题链接 洛谷原题链接 显然在原图上路线的总长为\(2(n-1)\). 添加第一条边时,显然会形成一个环,而这条环上的所有边全部只需要走一遍.所以为了使添加的边的贡献最大化,我们 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 【BZOJ2830/洛谷3830】随机树(动态规划)
[BZOJ2830/洛谷3830]随机树(动态规划) 题面 洛谷 题解 先考虑第一问. 第一问的答案显然就是所有情况下所有点的深度的平均数. 考虑新加入的两个点,一定会删去某个叶子,然后新加入两个深度 ...
- 树的直径初探+Luogu P3629 [APIO2010]巡逻【树的直径】By cellur925
题目传送门 我们先来介绍一个概念:树的直径. 树的直径:树中最远的两个节点间的距离.(树的最长链)树的直径有两种方法,都是$O(N)$. 第一种:两遍bfs/dfs(这里写的是两遍bfs) 从任意一个 ...
- 洛谷 [P3629] 巡逻
树的直径 树的直径有两种求法 1.两遍 dfs 法, 便于输出具体方案,但是无法处理负权边 2.DP 法,代码量少,可以处理负权边 #include <iostream> #include ...
随机推荐
- 【多线程】 Task ,async ,await
[多线程]Task ,async ,await 一. WinForm 里经常会用到多线程, 多线程的好出就不多说了,来说说多线程比较麻烦的地方 1. UI 线程与其他线程的同步,主要是 Form 和 ...
- Vue学习(三):数据绑定语法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Qt Charts_Audio实践
这里完全是照搬帮助文档中的代码生成的程序 上预览图 工程文件代码 #------------------------------------------------- # # Project crea ...
- Navicat oracle to postgresql ERR
可能的解决思路是设好源数据和目标数据库后,先建立表结构,然后修改表结构字段数据类型 参考 https://www.cnblogs.com/stephen-liu74/archive/2012/04/3 ...
- OpenStack配置虚拟机vcpu绑定步骤 转至元数据结尾
. Changed in compute node: 给宿主机预留资源: 宿主机可用cpu:cpuid – cpuid 宿主机可用内存:25G #vim /etc/nova/nova.conf vcp ...
- 合规P2P平台成PE/VC新宠
013年是互联网金融元年,余额宝.百发等掀起了大众理财的新一轮高潮.P2P平台作为互联网金融模式之一,也受到市场的重点关注-在部分平台不断爆出风险事件的同时,业内较为成熟的平台也正成为PE/VC的新宠 ...
- Spark实战练习01--XML数据处理
一.要求 将XML中的account_number.model数据提取出来,并以account_number:model格式存储 1.XML文件数据格式 <activations> < ...
- R6的压力测试
VersionCode:{102} VersionName:{1.0.2}
- Python标准模块logging
http://blog.csdn.net/fxjtoday/article/details/6307285 开发Python, 一直以来都是使用自己编写的logging模块. 比较土...... 今天 ...
- ui-grid从后端获取数据后更改数据显示的格式
从后端获取的数据时是这样的: { "TotalCount":14,"Items": [ { "ProfileId":14, "Na ...