1 条题解
-
0
#3412. 「2020-2021 集训队作业」不讲武德 题解
题目分析
给定一个连通无向图,每条边有两个权值 和 。对于每个 ,需要选出恰好 条边构成森林(无环),使得:
$$\text{cost} = \left(\sum_{i \in S} a_i\right) \times \left(\sum_{i \in S} b_i\right) $$最小,其中 是选中的边集。
核心思路
1. 问题转化
这是一个双目标最小生成树问题。对于固定斜率 ,定义边权:
按此边权求最小生成树,得到点 ,其中:
$$A(\lambda) = \sum_{i \in MST} a_i, \quad B(\lambda) = \sum_{i \in MST} b_i $$这些点构成的下凸包包含了所有可能的最优解。
2. 凸包性质
对于目标函数 ,最优解一定在凸包的左下部分。证明如下:
设 和 是凸包上相邻两点,对于 :
这是关于 的二次函数,最小值在端点处取得。
3. 分治算法
使用分治在凸包上寻找所有 对应的最优解:
def solve(l, r): # l, r 是凸包上的两个点 (A_l, B_l), (A_r, B_r) λ = -(A_r - A_l) / (B_r - B_l) # 计算斜率 # 用权值 w = a + λ*b 求最小生成树 mst = kruskal(λ) mid = (A_mst, B_mst) if mid 在 l 和 r 之间: solve(l, mid) 记录 mid 对应的答案 solve(mid, r)
4. 算法步骤
-
初始化:找到两个极端点
- :按 排序的MST
- :按 排序的MST
-
分治求解:在凸包上递归寻找所有可能的MST
-
合并答案:对于每个 ,取凸包上对应点的最小值
复杂度分析
- 凸包上最多 个点
- 每次Kruskal算法
- 总复杂度
- 满足数据范围
-
- 1
信息
- ID
- 3272
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者