有关消防一题中最优解一定在直径上的证明

P2491 [SDOI2011] 消防

P1099 [NOIP2007 提高组] 树网的核

题目描述

在一颗 \(n\) 个节点的无根树中,找到一条不超过 \(s\) 的路径,使得图中所有点到此路径距离的最大值最小,图中边权非负

分析

若想将此题转化到树网的核,需要证明对于任意一条不在直径上的路径,都能在直径上找到更优解

首先理解一个显然的结论:路径越长,结果越优

证明

以下过程中所用符号及其含义:

  • \(f(i)\) 表示从 \(i\) 出发不经过直径上的边所能到达的最长距离
  • \((u, v)\) 为树的直径, \(L\) 为直径长度
  • \((A, B)\) 为所取不在直径上的路径
  • \(d(i, j)\) 为 \(i\) 与 \(j\) 间的路径长

Part 1 : 所选路径与直径有交集



根据直径的最长性,很容易得到如下性质:

  1. 对于 \((A, C)\) 路径上的每一点\(i\), 都有\(f(i) \leq d(u, C)\)

如果大于,那么 $ f(i) + d(i, v) > L$, 与直径的最长性矛盾

  1. 对于\((D, B)\) 路径上的每一点 \(i\), 都有\(f(i) \leq d(D, v)\)

通过观察发现,只需截取 \((C, D)\) 就能满足1,2两条性质

由此我们可以将 \((A, C)\) 和 \((D, B)\) 称作是多余的,完全可以将\(AC, DB\) 的长度转化到直径上获得更优解



第一部分证毕。

Part 2 : 所选路径与直径无交集

\(x \leq y\) , \(y \geq \dfrac{L} {2}\)

设 \(val1\) 为图中所有点到 \(AB\) 的最大距离,则一定有

$$val1 = y + z $$

考虑用反证法证明:假设存在点 \(C\),使得 \(C\) 到 \(AB\) 的距离大于 \(val1\)

其中 \(C\) 到 \(AB\) 距离的最小值 $$d = val1 + 1$$

为了保证不重不漏,我们也把 \(C\) 到 \(AB\) 的路径划分为经过直径不经过直径两类

case 1:



$ d + z + y > L $ 矛盾

case 2:



\((d - w - z) + (x + w) = x + y + 1 > L\) 矛盾

因此 $ val1 = y + z $ 得证。

构造更优解



考虑在原图中只取点 \(O\) 作为所选路径

根据定义

\[val2 = max(x, y, f(O)) = y
\]

$f(O) \leq \dfrac{L}{2} $

整理一下

\[va1 = y + z, val2 = y
\]
\[val2 \leq val1
\]

第二部分证毕。

由于 \(z\) 可以取到0, 一种更严谨的说法是:对于任意一条与直径不相交的路径都不能在直径上构造出次优解

AC代码

#include<bits/stdc++.h>
#define ll long long using namespace std;
const ll N = 5e5 + 5; int n, vis[N], a[N];
ll s, d[N], sum[N]; vector<pair<int, ll> > H[N];
pair<int, ll> pre[N]; int bfs(int source) {
memset(d, -1, sizeof d);
queue<int> q;
q.push(source);
d[source] = 0;
while(!q.empty()) {
int x = q.front();
q.pop();
for(auto [y, z] : H[x]) {
if(d[y] == -1) {
d[y] = d[x] + z;
pre[y] = {x, z};
q.push(y);
}
}
}
int ret = source;
for(int i = 1; i <= n; ++ i) {
if(d[ret] < d[i]) ret = i;
}
return ret;
} void dfs(int x) {
vis[x] = 1, d[x] = 0;
for(auto [y, z] : H[x]) {
if(vis[y]) continue;
dfs(y);
d[x] = max(d[x], d[y] + z);
}
} int main() {
ios :: sync_with_stdio(0);
cin.tie(nullptr);
cin >> n >> s;
for(int i = 1, x, y, z; i < n; ++ i) {
cin >> x >> y >> z;
H[x].push_back({y, z});
H[y].push_back({x, z});
}
int u = bfs(1);
int v = bfs(u);
int p = v, idx; ll maxd = -2e9, ans = 2e9;
while(p != u) {
a[++ idx] = p;
p = pre[p].first;
}
a[++ idx] = u;
for(int i = 1; i <= idx; ++ i) vis[a[i]] = 1;
for(int i = 1; i <= idx; ++ i) {
dfs(a[i]);
sum[i] = sum[i - 1] + pre[a[i - 1]].second;
maxd = max(maxd, d[a[i]]);
}
for(int i = 1, j = 1; i <= idx; ++ i) {
while(sum[j + 1] - sum[i] <= s && j < idx) ++ j;
ans = min(ans, max({maxd, sum[i], sum[idx] - sum[j]}));
}
cout << ans;
return 0;
}

从[SDOI2011]消防 到[NOIP2007]树网的核的更多相关文章

  1. [SDOI2011]消防/[NOIP2007] 树网的核

    消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情,所以这个国家最兴旺的 ...

  2. NOIP2007 树网的核 && [BZOJ2282][Sdoi2011]消防

    NOIP2007 树网的核 树的直径的最长性是一个很有用的概念,可能对一些题都帮助. 树的直径给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和.树中最远的两个节点之间 ...

  3. Cogs 97. [NOIP2007] 树网的核 Floyd

    题目: http://cojs.tk/cogs/problem/problem.php?pid=97 97. [NOIP2007] 树网的核 ★☆   输入文件:core.in   输出文件:core ...

  4. noip2007 树网的核

    P1099 树网的核 112通过 221提交 题目提供者该用户不存在 标签动态规划树形结构2007NOIp提高组 难度提高+/省选- 提交该题 讨论 题解 记录   题目描述 设T=(V, E, W) ...

  5. 洛谷1099 [NOIP2007] 树网的核

    链接https://www.luogu.org/problemnew/show/P1099 题目描述 设T=(V,E,W)是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称TTT为 ...

  6. NOIP2007 树网的核 [提高组]

    题目:树网的核 网址:https://www.luogu.com.cn/problem/P1099 题目描述 设 T=(V,E,W)T=(V,E,W) 是一个无圈且连通的无向图(也称为无根树),每条边 ...

  7. BZOJ2282 SDOI2011消防/NOIP2007树网的核(二分答案+树形dp)

    要求最大值最小容易想到二分答案.首先对每个点求出子树中与其最远的距离是多少,二分答案后就可以标记上一些必须在所选择路径中的点,并且这些点是不应存在祖先关系的.那么如果剩下的点数量>=3,显然该答 ...

  8. noip2007树网的核

    想一下可以发现随便枚举一条直径做就可以了. 核越长越好.于是枚举核的过程可以做到O(n) 然后就是统计答案. 对于每个核最大偏心距肯定是核上面每个点不走核内的点所能走到的最远点的最值. 而且对于核的两 ...

  9. [SDOI2011] 消防 (树的直径,尺取法)

    题目链接 Solution 同 \(NOIP2007\) 树网的核 . 令 \(dist_u\) 为以 \(u\) 为根节点的子树中与 \(u\) 的最大距离. \(~~~~dis_u\) 为 \(u ...

  10. BZOJ1999或洛谷1099&BZOJ2282或洛谷2491 树网的核&[SDOI2011]消防

    一道树的直径 树网的核 BZOJ原题链接 树网的核 洛谷原题链接 消防 BZOJ原题链接 消防 洛谷原题链接 一份代码四倍经验,爽 显然要先随便找一条直径,然后直接枚举核的两个端点,对每一次枚举的核遍 ...

随机推荐

  1. 使用systemd部署r-nacos

    1. 前言 r-nacos是一个用rust实现的nacos服务.相较于java nacos来说,是一个提供相同功能,启动更快.占用系统资源更小(初始内存小于10M).性能更高.运行更稳定的服务. r- ...

  2. C#通过文件头判断flv文件

    代码如下: private void button1_Click(object sender, EventArgs e) { string path = Application.StartupPath ...

  3. 聊聊微信小程序的隐私协议开发

    为什么需要隐私协议? 小程序隐私授权弹窗FAQ官方:https://developers.weixin.qq.com/community/develop/doc/00000ebac5c3e042384 ...

  4. NFNet:NF-ResNet的延伸,不用BN的4096超大batch size训练 | 21年论文

    论文认为Batch Normalization并不是网络的必要构造,反而会带来不少问题,于是开始研究Normalizer-Free网络,希望既有相当的性能也能支持大规模训练.论文提出ACG梯度裁剪方法 ...

  5. 实现一个简单的echarts柱状图PythonFlask

    bar.html 1 <!DOCTYPE html> 2 <html style="height: 100%"> 3 <head> 4 < ...

  6. netty系列之:给ThreadLocal插上梦想的翅膀,详解FastThreadLocal

    目录 简介 从ThreadLocalMap中获取数据 FastThreadLocal 总结 简介 JDK中的ThreadLocal可以通过get方法来获得跟当前线程绑定的值.而这些值是存储在Threa ...

  7. SQL 的 AND、OR 和 NOT 运算符:条件筛选的高级用法

    AND 运算符 SQL的AND运算符用于根据多个条件筛选记录,确保所有条件都为TRUE才返回记录.下面是AND运算符的基本语法: SELECT column1, column2, ... FROM t ...

  8. 格式化字符串走过的坑 pwn109

    格式化字符串走过的坑 pwn109 今天做的一道题有一个坑我调试半天终于打通了,格式化字符串的坑,确实不少,东西也比较多容易忘记,怎么说呢,功夫在平时,经验少了 老规矩先看一下保护 Full RELR ...

  9. HarmonyOS SDK,赋能开发者实现更具象、个性化开发诉求

    随着移动互联网的逐步成熟,用户的需求越来越细化.鸿蒙生态为开发者提供的HarmonyOS SDK开放能力,高效赋能美团外卖等合作伙伴实现更具象.个性化的开发诉求,给用户提供更丰富便捷的体验. 点击链接 ...

  10. hive窗口分析函数使用详解系列二之分组排序窗口函数

    1.综述 我们讨论面试中各大厂的SQL算法面试题,往往核心考点就在于窗口函数,所以掌握好了窗口函数,面对SQL算法面试往往事半功倍. 已更新第一类聚合函数类,点击这里阅读 hive窗口函数聚合函数类 ...