1 条题解
-
0
D. 为了皇帝! 详细题解
问题重述
给定一个 个节点、 条有向边的图,每个节点 有 个信使()。信使可以沿有向边移动,可以在到达的城市无限复制计划给其他信使。初始时你可以选择一些信使,给他们一份计划。目标:最终每个城市都至少被一个携带计划的信使访问。求最少需要初始发放计划的数量,或判断不可能(输出 )。
关键观察
- 强连通分量内部:在一个强连通分量(SCC)内,信使可以到达分量内任意节点。因此,只要分量内至少有一个信使获得计划,整个分量的所有城市都可以被覆盖。
- 缩点后的 DAG:将原图缩点为 SCC 得到有向无环图(DAG)。每个 SCC 视为一个节点,其内部信使数量为分量内所有城市的信使数之和 。
- 问题转化:在 DAG 上,我们需要选择一些 SCC 作为“起始点”,使得从这些起始点出发,沿着有向边可以到达所有 SCC。每个起始点需要消耗一个计划(即给该分量内的某个信使一份计划)。但每个 SCC 可能有多个信使,我们可以选择不使用额外计划而依赖其他分量的信使传递进来。
网络流建模思路
我们要最小化初始发放计划的数量,等价于在 DAG 上找最少的“源”节点,使得所有节点都能被到达,并且每个节点 i 最多允许从它的信使中派出 条路径(每条路径对应一个信使传递计划的过程)。
标准解法是使用最小费用最大流(MCMF),构造一个流网络,使得流量代表计划传播的路径,费用代表我们主动发放的计划数量。
缩点与建图步骤
设缩点后共有 个 SCC,编号 。记 为第 个 SCC 的总信使数。
1. 基本流网络(判断可行性)
首先考虑是否存在一种方案使得所有 SCC 都能被覆盖(不管初始计划数量)。这等价于:能否在 DAG 上找到若干条路径,覆盖所有节点,且每个节点 出发的路径数不超过 (因为每个信使只能带一份计划出发,但可以在途中复制,所以出发路径数受限于初始信使数)。
经典构造:
- 将每个 SCC 拆成两个节点 和 ,中间连一条边 ,容量为 ,并强制这条边至少流过 (表示该 SCC 至少被一条路径覆盖)。
- 添加源点 和汇点 ,从 到 连容量 的边(表示从该 SCC 最多派出 条路径)。
- 从 到 连容量 的边。
- 对于原 DAG 中的边 ,从 到 连容量 的边。
- 强制 的流量至少为 ,这可以通过将这条边拆分为:保留容量 ,并增加一个辅助源汇强制流 (见下文)。
2. 转化为标准流问题
为了处理“至少 ”的约束,引入两个虚拟节点 和 :
- 对每个 ,从 到 连容量 的边(可理解为除了必须流的 之外还能多流)。
- 再从 到 连容量 的边。
- 再从 到 连容量 的边。
- 最后,从 到 连容量 的边(形成循环流)。
这样,从 到 的最大流若等于 ,则说明每个 SCC 都至少被一条路径覆盖,即存在可行方案。若最大流小于 ,则输出 。
3. 最小化初始计划数(最小费用)
在上述网络中,若从 到 的边每条流量代表一个信使从该 SCC 出发。我们想要最小化“主动发放计划”的数量,即那些没有从其他 SCC 获得计划、必须自己初始拥有的信使数。
在原网络中,每个 SCC 内的信使可以:
- 要么被其他 SCC 传来的计划“激活”(即该 SCC 的 边上的流量来自入边,而非从 出发),此时该 SCC 不需要主动发放计划;
- 要么自己作为源头,即从 到 的边上产生流量,此时需要消耗一个计划(因为要分给该 SCC 的一个信使)。
为了计算最小计划数,我们给从 出发的边赋予费用 ,其他边费用为 ,然后求从 到 且流量恰好为 的最小费用最大流。但注意,从 到 的边容量为 ,但每次激活该 SCC 可能不需要用满所有信使,我们只需至少有一条路径经过该 SCC。实际上,我们可以在每个 SCC 内部再增加一个中间节点 来控制费用。
更精确的构造(标程实现):
- 为每个 SCC 创建三个节点:、、。
- 连边:
- ,容量 ,费用 。
- ,容量 ,费用 (表示若该 SCC 作为源点,则花费 )。
- ,容量 ,费用 (表示信使可以直接流向 ,不消耗计划,但这样会导致没有经过 的强制流,需要配合其他边)。
- ,容量 ,费用 。
- ,容量 ,费用 。
- 添加 ,容量 ,费用 ;,容量 ,费用 。
- 添加 ,容量 ,费用 。
- 对于原 DAG 边 :,容量 ,费用 。
此时,从 到 的流量 表示每个 SCC 都被经过一次(强制流)。而 到 的流量中,通过 的那 个单位流量需要支付费用 ,表示该 SCC 需要主动发放一个计划;通过 的流量则不需要费用,但无法满足强制流(因为强制流要求经过 ),因此实际上每个 SCC 必须有且仅有 单位流量经过 ,这 单位要么来自 通过 (费用 ),要么来自其他 SCC 的 (费用 )。所以最小费用即为最少需要主动发放的计划数。
算法步骤
- 对原图跑 Tarjan 或 Kosaraju 求 SCC,得到缩点后的 DAG。
- 计算每个 SCC 的总信使数 。
- 建立上述 MCMF 网络,节点数 ,边数 。
- 运行最小费用最大流,从 到 求流量为 的最小费用。
- 若最大流小于 ,输出 ;否则输出最小费用。
复杂度
- SCC 缩点:。
- 网络流:节点数 ,边数 ,使用 SPFA 或 Dijkstra 势能优化,流量值 ,复杂度 可接受。
参考代码(标程已提供)
标程使用 Kosaraju 求 SCC,然后实现 MCMF(基于 SPFA 或类似算法)。代码中:
getInd(i)返回三个索引(uin, uout, ucnt)。MCMF类实现了最小费用最大流(使用类似 SPFA 的队列优化)。- 建图过程完全对应上述描述。
总结
本题是典型的图论与网络流结合问题,核心是将信使传播建模为覆盖所有节点的路径集,通过拆点、强制流和费用边来最小化源点数量。利用 SCC 缩点简化 DAG,再使用 MCMF 求解,是解决此类问题的标准方法。
- 1
信息
- ID
- 7180
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 1
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者