1 条题解
-
0
题目理解
我们需要计算一个无向连通图中所有 个点对的最小割容量中,不同数值的个数。
换句话说,对于所有 ,计算 ,然后统计这些值中有多少个不同的数。
直接方法的困难
直接枚举所有点对并计算最小割:
- 点对数量:
- 每次最小割计算: 或
- 总复杂度: 或 ,完全不可行
关键观察:Gomory-Hu 树
Gomory-Hu 定理:对于任意无向带权图,存在一棵树(称为 Gomory-Hu 树),使得:
- 树有 个节点,与原图节点一一对应
- 对于任意两点 ,原图中 最小割容量等于 Gomory-Hu 树中 路径上的最小边权
这意味着:
- 所有点对的最小割值 = Gomory-Hu 树中所有点对路径上的最小边权
- Gomory-Hu 树只有 条边
- 不同的最小割值 = Gomory-Hu 树中不同边权的数量
Gomory-Hu 树构建算法
递归分割算法:
- 从当前点集 中任选两点
- 计算 最小割,将 划分为 和
- 在 Gomory-Hu 树中添加边 ,权值为
- 递归处理 和
算法正确性:
- 每次找到的最小割对应 Gomory-Hu 树中的一条边
- 经过 次最小割计算即可构建整棵树
最小割计算:Stoer-Wagner 算法
由于我们只需要全局最小割(任意点对),可以使用 Stoer-Wagner 算法:
- 时间复杂度: 或
- 空间复杂度:
Stoer-Wagner 算法步骤:
while |V| > 1: 选择两个点 u, v 使得割 ({u}, V\{u}) 最小 记录当前最小割值 合并 u 和 v
算法流程
-
构建 Gomory-Hu 树:
- 使用递归分割 + Stoer-Wagner 算法
- 共进行 次最小割计算
-
统计不同边权:
- Gomory-Hu 树有 条边
- 将这些边的权值去重,计数即为答案
复杂度分析
- 每次 Stoer-Wagner 最小割:
- 共 次最小割计算:
- 对于 ,,勉强可过
优化
实际可以使用更高效的 Gomory-Hu 树构建方法:
- Gusfield 算法: 次最大流计算
- 使用 Dinic 或 ISAP 算法求最大流
- 复杂度:
对于稀疏图,这比 Stoer-Wagner 更高效。
样例验证
输入:
4 4 1 2 3 1 3 6 2 4 5 3 4 4构建 Gomory-Hu 树:
- 可能的 Gomory-Hu 树边权:3, 4, 7 等
- 不同值:3, 4, 7 → 3 个不同的最小割容量
输出:
3✓
实际高效实现
对于 ,更实用的方法是:
// 使用 Gusfield 算法构建 Gomory-Hu 树 set<int> gusfield() { set<int> cuts; int parent[N] = {0}; for (int i = 2; i <= n; i++) { // 计算 i 与 parent[i] 的最小割 int flow = maxFlow(i, parent[i]); cuts.insert(flow); // 更新 parent 数组 for (int j = i + 1; j <= n; j++) { if (parent[j] == parent[i] && inMinCut(j)) { parent[j] = i; } } } return cuts; }
总结
本题的关键在于:
- 理解 Gomory-Hu 树的理论基础
- 将原问题转化为 Gomory-Hu 树边权的去重计数
- 使用 Stoer-Wagner 或最大流算法计算最小割
- 注意算法复杂度与数据范围的匹配
这是一个典型的图论+算法优化问题,考察了对高级图论算法的理解和应用能力。
- 1
信息
- ID
- 4569
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者