首页 > 其他分享 >洛谷 P1099 题解

洛谷 P1099 题解

时间:2024-03-10 11:23:04浏览次数:17  
标签:洛谷 int 题解 delta ECC 直径 P1099 operatorname dis

洛谷 P1099 【NOIP 2007 提高组】 树网的核

题意简述

给定一棵带边权无根树和一个正整数 \(s\)。在这棵树的任意直径上截取一段长度不超过 \(s\) 的路径 \(F\),使离 \(F\) 最远的点到 \(F\) 的距离最小,求出这个距离。

思路

记 \(\delta(a, b)\) 为 \(a, b\) 之间的路径。

对于任意直径上一点 \(u\),记 \(d'(u)\) 为 \(u\) 不经过直径上其他点所能到达的最远距离。

如图,不妨设一条直径为 \(\delta(a, b)\),其中的一条路径 \(F = \delta(x, y)\) 满足 \(d(x, y) \le s\)。

引理: 对于直径 \(\delta(a, b)\) 上任意一点 \(u\),总有 \(d'(u) \le d(a, u), d(b, u)\)。

证明:假设 \(d'(u) > d(a, u)\),不妨设 \(u\) 不经过直径上其他点所能到达的最远的点是 \(a'\)(即 \(d'(u) = d(a', u)\)),则有 \(d(a', b) = d(a', u) + d(u, b) > d(a, u) + d(u, b) = d(a, b)\),与 \(\delta(a, b)\) 是树的直径矛盾。\(d'(u) \le d(b, u)\) 同理。

由引理及 \(\operatorname{ECC}\) 的定义可得出以下性质:

  1. \(z\) 对 \(\operatorname{ECC}(F)\) 的贡献是 \(d'(z)\)。

  2. \(x\) 对 \(\operatorname{ECC}(F)\) 的贡献是 \(d(a, x)\),\(y\) 对 \(\operatorname{ECC}(F)\) 的贡献是 \(d(b, y)\)。

  3. \(\operatorname{ECC}(F) \le \operatorname{ECC}(\delta(x, z_2)), \operatorname{ECC}(\delta(y, z_1))\)。

    证明:易得

    \[\begin{cases} \operatorname{ECC}(F) = \min\{d(a, x), d'(z_1), \cdots, d'(z_2), d(b, y) \}, \\ \operatorname{ECC}(\delta(x, z_2)) = \min\{d(a, x), d'(z_1), \cdots, d(b, z_2) \}, \\ \operatorname{ECC}(\delta(y, z_1)) = \min\{d(a, z_1), \cdots, d'(z_2), d(b, y) \}. \end{cases} \]

    由引理知 \(d'(z_1) \le d(a, z_1), d'(z_2) \le d(b, z_2)\),又易证 \(d(a, x) < d(a, z_1), d(b, y) < d(b, z_2)\),代入得证。

由 1、2 我们得知对于 \(F = \delta(x, y)\) 有 \(\operatorname{ECC}(F) = \max\{d(a, x), d(b, y), \max\{d'(z)\} \}\);由 3 我们得知仅当 \(d(x, y)\) 尽可能接近 \(s\) 时最优,这满足双指针的单调性。

使用两遍 DFS 找出一条直径,再使用一遍 DFS 求出直径上每个点的 \(d'\)。在这条直径上使用双指针枚举 \(x, y\) 确定 \(F\);\(d(a, x)\) 和 \(d(b, y)\) 可以在尺取的过程中得出,\(\max \{ d'(z) \}\) 可以用单调队列维护,由此求得 \(\operatorname{ECC}(F)\)。 \(\min \{\operatorname{ECC}(F) \}\) 即为答案。

DFS、双指针、单调队列时间复杂度均为 \(O(n)\),故总时间复杂度为 \(O(n)\)。

考虑进一步简化。在尺取的过程中求出所有 \(F\) 的 \(\max\{d(a, x), d(b, y) \}\) 的最小值,记为 \(r\);求出所有 \(d'\) 的最小值,记为 \(d'(t)\)。

设 \(F' = \delta(x', y')\) 是答案对应的区间。

  • 若 \(r \ge d'(t)\),则 \(\operatorname{ECC}(F') = \max\{d(a, x'), d(b, y' )\} = r\)。

  • 若 \(r < d'(t)\),则一定有 \(t\) 在 \(F'\) 上,即 \(x' \le t \le y'\),此时 \(\operatorname{ECC}(F') = d'(t)\)。假设 \(t\) 不在 \(F'\) 上,不妨设 \(t < x'\),由引理知 \(d'(t) \le d(a, t) < d(a, x) \le \operatorname{ECC}(F')\)​,一定不如前者优。

所以最终答案为 \(\max \{r, d'(t) \}\)。

考察存在多条直径的情况。题面已经指出直径的中点重合,可以证明每条直径不重合的两部分部分长度相等,如果 \(F'\) 包含了直径分岔的结点 \(m\),则 \(\operatorname{ECC}(F')\) 为 \(m\) 到 \(F'\) 末端的距离。具体证明较为繁琐,这里略去。

代码

#include <iostream>
#include <vector>

struct Edge // 边
{
    int to, w; // 终点和边权
};

int far; // 用于求直径端点

int fa[305], dis[305];     // fa 为父节点, dis 的用途不唯一
bool diameter[305];        // 是否在直径上
std::vector<Edge> mp[305]; // 存树

void dfs(int u, int f) // 求直径和 d'
{
    fa[u] = f;
    if (dis[u] > dis[far])
        far = u; // 求直径的端点
    for (auto i : mp[u])
        if (i.to != f && !diameter[i.to]) // i.to != f 避免死循环, !diameter[i.to] 是 d' 的定义
        {
            dis[i.to] = dis[u] + i.w;
            dfs(i.to, u);
        }
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    int n, s, ans = 300000;
    int start, end; // 直径的端点

    std::cin >> n >> s;
    for (int i = 1; i < n; i++)
    {
        int u, v, w;
        std::cin >> u >> v >> w;
        mp[u].push_back({v, w});
        mp[v].push_back({u, w});
    }

    dfs(1, 0);
    start = far;
    dis[start] = 0;
    dfs(start, 0); // 求出直径起点后, 顺便将直径起点作为树的根
    end = far;

    for (int i = end, j = end; i >= 1; i = fa[i]) // 双指针, i 即 x, j 即 y, 求出 max{d(a, x), d(b, y)}
    {
        while (dis[j] - dis[i] > s) // 性质 3
            j = fa[j];
        ans = std::min(ans, std::max(dis[end] - dis[j], dis[i]));
    }

    for (int i = end; i >= 1; i = fa[i]) // 标记直径, 为求 d' 做准备
        diameter[i] = true;

    for (int i = end; i >= 1; i = fa[i]) // 求 d'
    {
        dis[i] = 0;
        dfs(i, fa[i]);
    }

    for (int i = 1; i <= n; i++) // 求 d' 最大值
        ans = std::max(ans, dis[i]);

    std::cout << ans << "\n";

    return 0;
}

标签:洛谷,int,题解,delta,ECC,直径,P1099,operatorname,dis
From: https://www.cnblogs.com/lzy20091001/p/18063883/Luogu_P1099_Solution

相关文章

  • abc344_D - String Bags 题解
    一个月没有碰oi,感觉水平已经退化到负的了。来复健一下。D-StringBagslink题意:给你\(n\)组字符串组,按\(1\)~\(n\)的顺序,对于每组字符串组,可从中至多选一个字符串。求能否用所选串按顺序拼接成指定串,以及选取字符串的最小个数。然后读完题发现是个\(01\)背包;对于第......
  • AT_abc344_e 题解
    本文同步发表于洛谷。赌狗天天输的一集。赛时各种【数据删除】原因导致没做出来。大意给你一个长度为\(N\)的序列\(A=(A_1,\ldots,A_N)\)。保证\(A\)中的元素是不同的。你要处理\(Q\)个操作。每个操作是以下两种类型之一:1xy:在\(A\)中元素\(x\)后面紧接着插入......
  • AT_abc344_d 题解
    赌狗天天输的一集。大意你最开始有一个空字符串\(S\)。你还有编号为\(1,2,\dots,N\)的袋子,每个袋子都包含一些字符串。袋子\(i\)包含\(A_i\)个字符串\(S_{i,1},S_{i,2},\dots,S_{i,A_i}\)。对\(i=1,2,\dots,N\)重复以下步骤仅一次(这里原题没有讲清楚):......
  • P10238 [yLCPC2024] F. PANDORA PARADOXXX 题解
    分析考虑时光倒流。对于需要合并的两个连通块\(x,y\),其合并之后的最远点对距离一定是合并之前的两组点对中产生的。在合并的时候枚举点对,取距离最大值即可。由于我们是倒着来的,所有连通块的最远点对距离最大值不减,所以能直接在合并之后取最大值。维护连通块用并查集即可。复杂......
  • P10237 [yLCPC2024] E. Latent Kindom 题解
    分析一眼了非最优解。考虑二分答案。对于二分出来的中位数\(x\),到\(a_i\)和\(a_j\)里边又去二分。得到两个序列中不超过\(x\)的数的数量。若这个数量\(cnt\ge\lceil\frac{len_{i}+len_{j}}{2}\rceil\),则\(x\)可能成为中位数,然后继续二分即可。把序列离散化,复杂度......
  • [ABC219F] Cleaning Robot 题解
    [ABC219F]CleaningRobot题解思路解析要点:将整个图拆分成每一轮的每一个点单独考虑贡献。首先看到\(k\le10^{12}\)发现不能直接枚举\(k\)轮,于是开始找每一轮的规律。首先可以知道,如果操作固定,那么起点和路径上每一个点以及终点的相对位置不会改变。也就是说每一轮的起......
  • CF1583E Moment of Bloom 题解
    题意:给定一张\(n\)个点\(m\)条边无向连通图,以及\(q\)个点对\((a,b)\),出事每条边权值为\(0\)。对于每个点对我们需要找一条从一个点到另一个点的简单路径,将所有边的权值加一。要求构造一种方案使得每条边权值都是偶数。如果不行,输出最少还要几个点对才能满足要求。\(n,m......
  • CF1634E Fair Share 题解
    题意:给定\(m\)个长度为偶数的数组,\(L,R\)是初始为空的两个多重集。将每个数组恰好一半的数放入\(L\),另一半放入\(R\),要求最后\(L=R\),要求构造方案或判断无解。\(m\le10^5,\sumn\le10^5\)。思路:首先我们不难想到,对于同一个数组内相同的值,可以成双除去,所以我们可以......
  • Interval GCD 题解
    题目描述给定一个长度为\(\largen\)的数组\(\largea\),以及\(\largem\)条指令(\(n\leq5\times10^5,m\leq10^5\)),每条指令可能是以下两种之一:“\(\large\operatorname{C\l\r\d}\)”,表示把\(\largea[l],a[l+1],…,a[r]\)都加上\(\larged\)。“\(\large\operatorn......
  • CF1264D2 Beautiful Bracket Sequence (hard version) 题解
    括号深度的本质,其实就是删除若干个字符以后使得左边一半全是(,右边一半全是),最终(的个数的最大值。那么就一定存在一个位置使得在这个位置以及之前的字符中(的个数等于这个字符后)的个数。考虑枚举这个位置,记它左边的(的个数为\(a\)、?的个数为\(x\),右边的)的个数......