1 条题解

  • 0
    @ 2026-4-3 1:13:08

    E1. 数字村庄(简单版本)详细题解

    1. 问题重述

    • 有一个 nn 个顶点 mm 条边的连通简单图n400n \le 400n1m400n-1 \le m \le 400)。
    • pp特殊顶点(需要互联网的房屋)s1,s2,,sps_1, s_2, \dots, s_p
    • 我们可以选择至多 kk 个顶点放置服务器。
    • 每个特殊顶点会连接到某个服务器,路径延迟定义为该路径上最大边权
    • 目标:最小化所有特殊顶点的延迟之和

    对每个 k=1,2,,nk = 1, 2, \dots, n 输出最小总延迟。


    2. 关键转化

    如果我们固定了服务器集合 SSSk|S| \le k),那么对于一个特殊顶点 uu,它的延迟为:

    minsSmaxepath(u,s)we\min_{s \in S} \max_{e \in \text{path}(u, s)} w_e

    这其实就是 uuSS 的最小化最大边权,即:

    $$d(u, S) = \min_{s \in S} \text{(minimum spanning tree path max edge weight)} $$

    3. 最小瓶颈路径与 MST

    在图论中,两点之间路径的最大边权的最小值,等于最小生成树(MST)上这两点之间路径的最大边权。
    因为 MST 满足
    最小瓶颈路径性质

    所以我们可以先求出图的 MST,之后所有问题都在 MST 上考虑(n1n-1 条边)。


    4. 转化到树上

    TT 为原图的 MST,边权为 wew_e

    对于树上任意两点 u,vu,v,定义:

    $$\text{maxEdge}(u,v) = \max_{e \in \text{path}_T(u,v)} w_e $$

    uu 到服务器集合 SS 的延迟为:

    d(u,S)=minsSmaxEdge(u,s)d(u,S) = \min_{s \in S} \text{maxEdge}(u,s)

    5. 进一步转化:Kruskal 重构树(KRT)

    Kruskal 重构树是解决这类“路径最大边权最小值”问题的标准工具。

    构造方法(按边权升序):

    • 初始有 nn 个叶子节点,权值为 00(或 -\infty)。
    • 每次合并两个连通块时,新建一个节点,权值为当前边权,作为这两个连通块根节点的父节点。
    • 最终形成一棵 2n12n-1 个节点的二叉树(或森林,但原图连通,所以是一棵树)。

    性质:
    在原树 TT 中,两点 u,vu,v 的路径最大边权等于它们在 KRT 中的 LCA 的权值

    因此:

    $$\text{maxEdge}(u,v) = \text{val}[\text{LCA}_{\text{KRT}}(u,v)] $$

    6. 问题转化为 KRT 上的问题

    在 KRT 上,叶子节点是原图的顶点(1..n1..n),内部节点对应原 MST 的边(按边权从小到大)。

    设叶子集合 PP 为需要互联网的顶点(pp 个)。

    选择 kk 个叶子作为服务器(也可以选内部节点吗?题目说服务器可以安装在任意房屋,即任意顶点,对应 KRT 的叶子节点)。
    注意:服务器只能放在原图顶点,即 KRT 的叶子节点。


    7. 动态规划思路(基于 KRT)

    我们可以用树形 DP 解决:
    dp[u][t]dp[u][t] 表示在 KRT 的子树 uu 中,放置恰好 tt 个服务器(在叶子节点),能覆盖的 PP 中顶点的最小总延迟

    但是这里延迟是“路径上最大边权”,在 KRT 中,如果某个 PP 中顶点 xx 被子树 uu 内的服务器覆盖,它的延迟就是 xx 到该服务器的 LCA 的权值,这个 LCA 一定在 xxuu 的路径上。
    这很复杂。


    8. 经典转化:考虑每条边对答案的贡献

    另一种更简单的方法(常见于此类问题):

    对于 MST 上的每条边 ee(权值 ww),如果把它删掉,树会分成两个连通块 AABB
    如果 AA 中有服务器,BB 中也有服务器,那么这条边不会被任何 PP 中顶点跨过?等等,我们想的是:
    一个 PP 中顶点的延迟,等于它到最近服务器的路径上最大边权
    所以最大边权就是路径上最重的那条边。


    9. 等价于:每条边是否贡献到总延迟

    对于一个 PP 中顶点 uu,设它到最近服务器的路径为 usu \to s,路径上的最大边权记为 WuW_u
    那么总延迟 = uPWu\sum_{u \in P} W_u

    我们考虑每条边 ee(权值 ww)被哪些 uu 的路径经过,并且 wwuu 到其最近服务器的路径上的最大值。
    这等价于:
    在 KRT 中,从 uu 向上走到第一个权值大于等于 ww 的祖先?有点绕。


    10. 更简洁的解法(官方常见做法)

    由于 n400n \le 400,我们可以用最小化最大边权的聚类思想:

    我们按边权升序排序 MST 的边。
    假设我们想用 kk 个服务器覆盖所有 PP,那么总延迟可以看成:
    PP 划分成 kk 组,每组选一个服务器(可以是组内任意点),组内点到服务器的最大边权为该组的成本,总成本 = 各组成本之和。

    但组内点到服务器的最大边权 = 该组在 MST 上的最小斯坦纳树的最大边权?
    实际上,如果组内点集为 QQ,最优服务器位置是 QQ中心(最小化到所有点的最大边权),这个中心就是 QQ 在 MST 上的最优点,可以证明中心在 QQ 的 MST 子图的中心(树的中心)。


    11. 最终简化:二分 + 贪心

    由于 nn 小,我们可以这样做:

    1. 预处理任意两点 u,vu,vmaxEdge(u,v)\text{maxEdge}(u,v)O(n2logn)O(n^2 \log n) 或 Floyd 在树上 O(n2)O(n^2))。
    2. 问题变为:选 kk 个服务器,最小化 uPminsSmaxEdge(u,s)\sum_{u \in P} \min_{s \in S} \text{maxEdge}(u,s)

    这类似于 k-median 问题,但距离度量是 maxEdge\text{maxEdge}

    由于 n400n \le 400,我们可以用 DP + 树形背包 在 KRT 上做:

    • 在 KRT 上,每个内部节点 vv 代表一个边权 wvw_v
    • 如果 PP 中某叶子 xx 的最近服务器在子树 vv 外部,则 xx 的延迟至少为 wvw_v
    • 可以设计 DP:dp[u][t]dp[u][t] 表示子树 uu 内放 tt 个服务器,子树内 PP 点的最小总延迟,其中延迟计算要考虑跨过 uu 的边的贡献。

    12. 具体 DP 定义(最终解法)

    定义 KRT 的每个节点 uu 代表一个连通块,权值 val[u]val[u] 表示合并时的边权(叶子节点 val=0val=0)。

    对于叶子节点(原图顶点):

    • 如果它是 PP 中的点,它需要被覆盖;如果不是,它不需要。

    f[u][t]f[u][t] 表示在子树 uu 中放置 tt 个服务器,且子树内所有 PP 中顶点都被覆盖时,这些顶点的最小总延迟(延迟计算只考虑子树内部的路径,跨过 uu 的边的延迟会在父节点处理)。

    初始化叶子 uu

    • 如果 uPu \in Pf[u][1]=0f[u][1] = 0(放一个服务器,延迟 0),f[u][0]=f[u][0] = \infty(不放服务器,无法覆盖)。
    • 如果 uPu \notin Pf[u][0]=0f[u][0] = 0(不放服务器也没关系),f[u][1]=0f[u][1] = 0(放服务器也没用,不影响)。

    转移(合并两个孩子 llrruu):

    • 我们枚举左子树放 xx 个服务器,右子树放 yy 个,总 t=x+yt = x + y
    • 如果 uu 是内部节点(对应一条边权 ww),那么左右子树的 PP 点如果被另一子树的服务器覆盖,则路径必须经过 uu,那么这些点的延迟至少为 ww
    • 因此,我们需要额外记录:是否左右子树有服务器。如果没有跨子树覆盖,就不加 ww;如果有跨子树覆盖,就要加 w×w \times (被跨子树覆盖的 PP 点数)。

    更简洁的常见实现是:

    • 对每个 uu,计算 cnt[u]cnt[u] = 子树内 PP 点数。
    • 合并时,考虑跨过 uu 的边的贡献:
      如果左子树没放服务器且右子树有 PP 点,那么右子树的 PP 点会被左子树的服务器覆盖吗?不行,因为左子树没服务器。
      实际上,我们需要知道每个子树是否至少有一个服务器。

    因此状态改为:dp[u][t][0/1]dp[u][t][0/1] 表示子树 uu 内放 tt 个服务器,且 uu 的连通块内是否有服务器,的最小总延迟。


    13. 最终算法步骤

    1. 建原图 MST。
    2. 建 Kruskal 重构树(2n12n-1 个节点)。
    3. 树形 DP:
      • 叶子:dp[u][0][0]=0dp[u][0][0] = 0(如果 uPu \notin P),dp[u][1][1]=0dp[u][1][1] = 0(如果 uPu \in PuPu \notin P 但放服务器),但注意 uPu \notin P 时放服务器无意义但可行。
      • 内部节点 uu 合并左右孩子 l,rl,r,边权 w=val[u]w = val[u]
      • 转移时枚举 ll 的服务器数 aarrbb,以及 ll 是否有服务器 f1f1rr 是否有服务器 f2f2
      • 总服务器数 t=a+bt = a + b
      • 总延迟 = dp[l][a][f1]+dp[r][b][f2]+w×dp[l][a][f1] + dp[r][b][f2] + w \times (跨子树覆盖的 PP 点数)。
      • 跨子树覆盖的点数 = 如果 f1=0f1=0f2=1f2=1,则 rrPP 点被 uu 外覆盖,要加 cnt[r]cnt[r];如果 f1=1f1=1f2=0f2=0,则加 cnt[l]cnt[l];如果都有服务器,则不加(因为两边内部覆盖);如果都没有,则 uu 的父节点会处理。
    4. 最后,根节点 rootrootdp[root][k][1]dp[root][k][1] 就是答案(根必须有服务器,否则无法覆盖整棵树)。
    5. k=1..nk=1..n 输出最小值。

    复杂度 O(n2)O(n^2),因为合并时枚举 a,ba,b 总次数为 O(n2)O(n^2)(树形背包)。


    14. 时间复杂度

    • 建 MST:O(mlogm)O(m \log m)
    • 建 KRT:O(nlogn)O(n \log n)
    • DP:O(n2)O(n^2),满足 n400n \le 400

    这样我们就得到了一个完整、可实现的解法。

    • 1

    信息

    ID
    6312
    时间
    1000ms
    内存
    256MiB
    难度
    2
    标签
    递交数
    1
    已通过
    1
    上传者