GCJ - 哈密顿循环

时间:2011-05-17 23:36:02

标签: algorithm graph hamiltonian-cycle

Code jam problem如下:

您将获得一个包含N个节点和K“禁止”边缘的完整无向图。 N <= 300,K <= 15.在图中找出不使用任​​何K“禁止”边缘的哈密顿循环数。

不幸的是,这里对堆栈和整个网络的解释都非常不充分。我可以找出HamCycles的某个'n':( n-1)! / 2。

我可以通过动态编程做短片。

但我没有得到博洛尼亚的所有子集,如何让它成为O ^ K?我是Python的,还没有破译可用的C ++。最后我确定我会花时间学习C ++,然后我会解读它。但与此同时,为什么有人不能在网络上的某个地方更好地解释这一点?他们总是有一半的解释。

1 个答案:

答案 0 :(得分:8)

如果你指出缺乏的解释可能会有所帮助,但无论如何我都会尝试......

基于O(2 k )的解决方案使用inclusion-exclusion principle。鉴于 k 禁止边缘,有 2 k 这些子集边缘,包括集合本身和空集。例如,如果有3个禁带:{A,B,C},则会有2个 3 = 8个子集:{},{A},{B},{C},{ A,B},{A,C},{B,C},{A,B,C}。

对于每个子集,您计算至少包含该子集中所有边的周期数。如果包含边 s 的周期数为 f(s) S < / em> 是所有禁用边的集合,然后通过包含 - 排除原则,没有任何禁止边的循环数是:

 sum, for each subset s of S: f(s) * (-1)^|s|

其中| s |是 s 中元素的数量。换句话说,任意边的周期数总和减去至少有1个禁止边的周期数加上至少有2个禁边的数字,。 ..

计算 f(s) 并非易事 - 至少我找不到一种简单的方法。你可以在阅读之前停下来思考它。

要计算 f(s) ,请从未与任何 s 相关的节点的排列数开始节点。如果 m 此类节点,则 m !如你所知,排列。调用排列数 c

现在检查链中 s 的边缘。如果存在任何不可能的组合,例如涉及3条边的节点或 s 中的子循环,则 f(s) 是0。

否则,对于每个链增量 m 增加1并将 c 乘以 2米 即可。 (有 m 的位置将链放在现有的排列中,因子2是因为链可以向前或向后。)最后, f(s) c /( 2m )。最后一个分区将排列转换为循环。