2

代码堵塞问题如下:

你得到一个完整的无向图,有 N 个节点和 K 个“禁止”边。N <= 300, K <= 15。找出图中不使用任何 K 个“禁止”边的哈密顿循环数。

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

我可以用动态编程做短集。

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

4

1 回答 1

8

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

基于 O(2 k ) 的解决方案使用包含-排除原则。假设有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是所有禁止边的集合,则根据包含-排除原理,没有任何禁止边的循环数为:

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

在哪里 | 小号| 是s中的元素数。换句话说,任何边的循环数之和减去至少有 1 个禁止边的循环数加上至少有 2 个禁止边的循环数,...

计算f(s)并非易事——至少我没有找到一种简单的方法来做到这一点。在继续阅读之前,您可能会停下来思考一下。

要计算f(s),请从不涉及任何s节点的节点的排列数开始。如果有m个这样的节点,则有m个!排列,如你所知。调用排列数c

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

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

于 2011-05-20T03:04:15.630 回答