首先,感谢您发布一个非常有趣的问题。完成这项工作非常有趣!
我想出的减少是从 3SAT 到您的问题。直观地说,减少工作如下:我们构建一个由两个平行的级联节点组成的图(我们称它们为左分支和右分支)。左分支边缘对应于公式中的变量,右分支对应于公式中的子句。我们将构建图表,使两条路径对应于为满足所有子句的公式选择一个变量赋值。
强制变量取值的左分支构建如下。对于每个变量 x,构建一个如下所示的小工具:
*
true --> / \ <-- false
* *
\ /
*
从顶部节点开始,“左”表示“x 为真”,“右”表示“x 为假”。我们将为每个变量构建此小工具的一个副本,并将它们从上到下链接。因此,从链的顶部到底部的路径对应于为命题公式选择一个变量分配。
右分支的构建方式类似。假设我们有一个子句 x &lor; y &lor; z。然后我们构建这个小工具:
*
/|\
* * *
\|/
*
这里,左分支对应“x 为真”,中间分支对应“y 为真”,右分支对应“z 为真”。这个想法是,我们需要每个子句至少有一个真正的文字,我们将通过选择要走的路径来选择哪个文字。
现在,我们构建约束集。对于每个变量 x,我们要确保如果在左分支中我们说 x 为真,我们不会跟随右分支中 x 应该为假的边缘。因此,我们将创建一个约束集,其中包含来自左分支的边“x 为真”和来自右分支的“x 为假”的所有副本。我们将类似地创建第二个约束集,其中包含来自左分支的边“x 为假”和来自右分支的所有标记为“x 为真”的边。这些约束集共同确保如果我们通过左分支和右分支的路径,我们为每个变量选择一个值(通过左分支的路径)并为每个子句选择至少一个真正的文字(通过右支)。
为了完成这一切,我们将创建一个新的起始节点 S 和一个新的终端节点 T,将 S 连接到左分支的第一个节点和右分支的第一个节点,并将左分支的最后一个节点和右分支到 T。现在,当且仅当有两个节点不相交的路径从 S 到 T 尊重所有约束时,公式才有令人满意的分配。做一些快速的数学运算表明,如果公式有 n 个变量和 m 个子句,那么通过左分支的路径的长度将是 2n + 2,通过右分支的路径的长度将是 2m + 2,所以公式当且仅当有一对从 S 到 T 的节点不相交路径的组合长度为 2n + 2m + 4 时是可满足的。请注意,如果公式不可满足,则根本没有合法路径。
希望这会有所帮助!