Skip to content
NotesAlgorithm

算法设计与分析课程笔记,覆盖分治、图算法、网络流、线性规划与复杂度基础。

More NP-Complete Problems ​

这一讲继续 NP-completeness,重点不是重新定义 P、NP,而是练习如何写 reduction proof,以及如何从已有 NP-complete 问题推出更多 NP-complete problems。

这份笔记先补充课件中的 reduction graph,再补上一个很常用的基本归约:

IndependentSet≤KVertexCover

Reduction Graph ​

课件中的 reduction graph 表达的是:从已经知道的 NP-complete 问题出发,沿着 Karp reduction 的箭头,可以证明更多问题 NP-complete。

可以直接看课件中的 reduction graph:

Our Reduction Graph

这里每条箭头:

A→B

表示:

A≤KB

也就是:如果能在多项式时间内解决 B,就能在多项式时间内解决 A。因此 B 至少和 A 一样难。

结合 Cook-Levin Theorem:

SAT is NP-complete

以及 reduction 的传递性,就能得到图中后续问题的 NP-hardness。若再证明目标问题本身在 NP 中,就得到 NP-completeness。

常见主线包括:

SAT≤K3SAT≤KIndependentSetIndependentSet≤KVertexCoverIndependentSet≤KCliqueVertexCover≤KDominatingSetVertexCover≤KSubsetSum

以及 Hamiltonian path / cycle 相关归约。

How to Prove NP-completeness ​

证明一个问题 f 是 NP-complete,通常写四步:

  1. 证明 f∈NP。
  2. 选一个已知 NP-complete 问题 g。
  3. 给出多项式时间归约:
g≤Kf
  1. 证明 yes/no instance 被正确保持:
x is yes for g⟺R(x) is yes for f

一个常见错误是把方向写反。要证明 f 难,应该把已知难问题 g reduce 到 f,而不是把 f reduce 到 g。

Independent Set Reduces to Vertex Cover ​

这一节补充:

IndependentSet≤KVertexCover

Problems ​

Independent Set:

给定无向图 G=(V,E) 和整数 k,判断 G 中是否存在大小为 k 的 independent set。

一个点集 S⊆V 是 independent set,意思是 S 中任意两个点之间都没有边。

Vertex Cover:

给定无向图 G=(V,E) 和整数 k′,判断 G 中是否存在大小为 k′ 的 vertex cover。

一个点集 C⊆V 是 vertex cover,意思是每条边都至少有一个端点在 C 中。

Key Observation ​

核心观察是:

S is an independent set of G⟺V∖S is a vertex cover of G

直观解释:

  • 如果 S 是 independent set,那么 S 内部没有边;
  • 所以任意一条边不可能两个端点都落在 S;
  • 因此每条边至少有一个端点在 V∖S;
  • 这正说明 V∖S 是 vertex cover。

反过来,如果 C 是 vertex cover,那么每条边至少有一个端点在 C。于是 V∖C 中不可能包含一条边的两个端点,所以 V∖C 是 independent set。

Reduction ​

给定 Independent Set instance:

(G,k)

构造 Vertex Cover instance:

(G,|V|−k)

也就是说,图不变,只把参数从 k 改成 |V|−k。

这个构造显然可以在多项式时间内完成。

Correctness ​

先证 yes instance 会变成 yes instance。

如果 G 中存在大小为 k 的 independent set S,那么由 key observation:

V∖S

是 vertex cover,并且大小是:

|V∖S|=|V|−k

所以构造出的 Vertex Cover instance:

(G,|V|−k)

是 yes instance。

再证反方向。

如果构造出的 Vertex Cover instance 是 yes,也就是 G 中存在大小为 |V|−k 的 vertex cover C,那么由 key observation:

V∖C

是 independent set,并且大小是:

|V∖C|=k

所以原来的 Independent Set instance:

(G,k)

也是 yes instance。

因此 no instance 也会变成 no instance。

反证:如果原来的 Independent Set instance (G,k) 是 no,但构造出的 Vertex Cover instance (G,|V|−k) 是 yes,那么由上面的反方向证明,可以推出 (G,k) 也是 yes instance,矛盾。

所以:

(G,k)∉IndependentSet⇒(G,|V|−k)∉VertexCover

因此:

(G,k)∈IndependentSet⟺(G,|V|−k)∈VertexCover

即:

IndependentSet≤KVertexCover

Why This Proves Vertex Cover Is NP-complete ​

上一讲已经有:

SAT≤K3SAT≤KIndependentSet

并且 SAT 是 NP-complete,所以 IndependentSet 是 NP-complete。

现在又有:

IndependentSet≤KVertexCover

因此 VertexCover 是 NP-hard。

还需要证明:

VertexCover∈NP

certificate 可以是一个点集 C。Verifier 检查:

  1. |C|=k;
  2. 对每条边 (u,v)∈E,检查是否 u∈C 或 v∈C。

这可以在多项式时间内完成。

所以:

VertexCover is NP-complete

Independent Set Reduces to Clique ​

证明:

IndependentSet≤KClique

Clique ​

k-Clique Problem:

给定无向图 G=(V,E) 和整数 k,判断 G 是否存在大小为 k 的 clique。

clique 指任意两个点之间都有边的点集。

Key Observation ​

令 G― 表示 G 的 complement graph:

  • G 中有边的点对,在 G― 中没有边;
  • G 中没有边的点对,在 G― 中有边。

那么:

S is an independent set in G⟺S is a clique in G―

Reduction ​

给定 Independent Set instance:

(G,k)

构造 Clique instance:

(G―,k)

Correctness ​

先证 yes instance 会变成 yes instance。

如果 G 中存在大小为 k 的 independent set S,那么 S 中任意两个点在 G 中都没有边。 根据 complement graph 的定义,这些点在 G― 中两两相连。 所以 S 是 G― 中大小为 k 的 clique。

因此:

(G,k)∈IndependentSet⇒(G―,k)∈Clique

再证 no instance 会变成 no instance。

反证:假设 (G,k) 是 Independent Set 的 no instance,但 (G―,k) 是 Clique 的 yes instance。 那么 G― 中存在大小为 k 的 clique S。

因为 S 中任意两个点在 G― 中都有边,所以它们在 G 中都没有边。 于是 S 是 G 中大小为 k 的 independent set。

这说明 (G,k) 是 Independent Set 的 yes instance,矛盾。

所以:

(G,k)∉IndependentSet⇒(G―,k)∉Clique

综上:

(G,k)∈IndependentSet⟺(G―,k)∈Clique

因此:

IndependentSet≤KClique

如果 Clique 也在 NP,那么 Clique 是 NP-complete。

Vertex Cover Reduces to Dominating Set ​

证明:

VertexCover≤KDominatingSet

这里使用常见的 decision 版本:判断是否存在大小 至多 为 k 的解。

如果 k=0 或 E=∅,Vertex Cover instance 可以直接在多项式时间内判断,然后输出一个固定的 yes/no Dominating Set instance。 例如,yes instance 可以输出单点图配参数 1;no instance 可以输出单点图配参数 0。 所以下面的构造只讨论非平凡情形:k≥1 且 E≠∅。

Dominating Set ​

Dominating Set Problem:

给定无向图 H=(U,F) 和整数 k,判断 H 是否存在大小至多为 k 的 dominating set。

一个点集 D⊆U 是 dominating set,意思是每个点要么在 D 中,要么至少有一个邻居在 D 中。

换句话说,D 可以“覆盖”所有点:

∀u∈U,u∈D or N(u)∩D≠∅

Construction ​

给定 Vertex Cover instance:

(G=(V,E),k)

构造一个 Dominating Set instance:

(H,k)

其中 H 的构造如下:

  1. 保留 G 中的每个原始点 v∈V;
  2. 把所有原始点 V 两两相连,使它们形成一个 clique;
  3. 对 G 中每条边 e=(u,v),新增一个点 xe;
  4. 只把 xe 连到这条边的两个端点 u 和 v。

也就是说:

U=V∪{xe:e∈E}

并且每个新增点 x(u,v) 只和 u,v 相邻。

这个构造显然可以在多项式时间内完成。

Key Observation ​

核心观察是:

  • 原始点 V 被做成了 clique,所以只要选中任意一个原始点,就能 dominate 所有原始点;
  • 每个新增点 x(u,v) 只能被 u、v 或它自己 dominate;
  • 如果 dominating set 里选了某个新增点 x(u,v),可以把它换成 u,不会让 domination 变差。

因此,如果 H 有大小至多为 k 的 dominating set,那么可以假设这个 dominating set 只包含原始点 V。

在这种情况下,要 dominate 每个新增点 x(u,v),就必须从 u,v 中至少选一个点。

这正是 vertex cover 的条件。

Correctness ​

先证正方向。

如果 G 有大小至多为 k 的 vertex cover C,那么 C 也是 H 的 dominating set:

  • 在非平凡情形下 C 非空;因为 C⊆V,而 V 在 H 中是 clique,所以 C dominate 所有原始点;
  • 对每个新增点 x(u,v),因为 C 是 vertex cover,所以 u,v 至少有一个在 C 中,因此 x(u,v) 也被 dominate。

所以:

(G,k)∈VertexCover⇒(H,k)∈DominatingSet

再证反方向。

如果 H 有大小至多为 k 的 dominating set D,根据 key observation,可以把其中的新增点都替换成对应的原始端点,得到一个只包含原始点的 dominating set D′⊆V,并且:

|D′|≤|D|≤k

由于 D′ dominate 每个新增点 x(u,v),而 x(u,v) 只和 u,v 相邻,所以 u,v 中至少有一个在 D′ 中。

因此 D′ 覆盖了 G 中的每条边,也就是 G 的 vertex cover。

所以:

(H,k)∈DominatingSet⇒(G,k)∈VertexCover

因此 no instance 也会变成 no instance。

反证:如果原来的 Vertex Cover instance (G,k) 是 no,但构造出的 Dominating Set instance (H,k) 是 yes,那么由上面的反方向证明,可以推出 (G,k) 也是 Vertex Cover 的 yes instance,矛盾。

所以:

(G,k)∉VertexCover⇒(H,k)∉DominatingSet

综上:

(G,k)∈VertexCover⟺(H,k)∈DominatingSet

即:

VertexCover≤KDominatingSet

由于 VertexCover 是 NP-complete,并且 DominatingSet∈NP,所以:

DominatingSet is NP-complete

Take Home Messages ​

  1. Reduction graph 的箭头方向表示 A≤KB,即 B 至少和 A 一样难。
  2. 证明目标问题 NP-complete 时,必须从已知 NP-complete 问题归约到目标问题。
  3. IndependentSet≤KVertexCover 的核心是补集关系:
S independent⟺V∖S vertex cover
  1. 输入转换非常简单:
(G,k)↦(G,|V|−k)
  1. 由于 IndependentSet 是 NP-complete,且 VertexCover∈NP,所以 VertexCover 也是 NP-complete。
  2. VertexCover≤KDominatingSet 的核心是:给每条边新增一个点,逼迫 dominating set 至少选择这条边的一个端点。

Cook-Levin Theorem ​

Cook-Levin Theorem:

SAT is NP-complete.

也就是说:

  1. SAT∈NP;
  2. 对任意 f∈NP,都有:
f≤KSAT

Proof Sketch ​

已经知道 SAT∈NP,关键是证明任意 NP 问题都能 reduce 到 SAT。

设 f∈NP。根据 NP 的定义,存在 polynomial time verifier A。

对于 instance x:

  • 如果 x 是 yes instance,则存在 polynomial length certificate y,使得 A(x,y) accepts;
  • 如果 x 是 no instance,则所有 y 都不能让 A(x,y) accepts。

Cook-Levin 的核心想法:

用一个 Boolean formula 模拟 verifier A 在输入 (x,y) 上的整段计算过程。

可以把 Turing Machine 的计算过程写成 tableau:

时间步tape 内容head 位置state
step 0输入 x 和未知 certificate y初始位置start
step 1下一步 tape新位置新状态
⋯⋯⋯⋯
final step最终 tape最终位置accept/reject

然后为 tableau 中的每个 cell、每个时间步、每个状态建立 Boolean variables,并用 CNF 约束表达:

  1. step 0 中固定了输入 x;
  2. certificate y 可以自由选择;
  3. final step 必须是 accept;
  4. 每一步到下一步必须符合 A 的 transition function。

这些约束可以在 polynomial size 内写成 CNF formula。

于是构造出的 formula 可满足,当且仅当存在 certificate y 让 A(x,y) accepts。

因此:

x∈f⟺ϕx∈SAT

这给出了:

f≤KSAT

因为 f 是任意 NP 问题,所以 SAT 是 NP-hard;又因为 SAT 本身在 NP,所以 SAT 是 NP-complete。

More NP-complete Problems ​

有了 Cook-Levin Theorem 和 reduction 传递性,可以证明大量问题都是 NP-complete。

课件中涉及的典型关系:

SAT≤K3SAT≤KIndependentSet

还包括:

IndependentSet≤KVertexCover

以及:

IndependentSet≤KClique

因为 SAT 是 NP-complete,如果我们能从 SAT 一路 reduce 到某个问题 H,并且 H∈NP,那么 H 也是 NP-complete。

3SAT Reduces to Hamiltonian Path ​

目标是证明:

3SAT≤KHamiltonianPath

课件里常用一个中间问题:

3SAT≤KDirectedHamiltonianPath≤KHamiltonianPath

Directed Hamiltonian Path ​

Directed Hamiltonian Path:

给定有向图 G=(V,E)、source s 和 sink t,判断是否存在一条从 s 到 t 的 directed path,恰好经过每个顶点一次。

Step 1: 3SAT to Directed Hamiltonian Path ​

给定一个 3SAT instance:

ϕ=C1∧C2∧⋯∧Cm

变量为:

x1,x2,…,xn

我们构造一个有向图,使得:

ϕ is satisfiable⟺Gϕ has an s-t directed Hamiltonian path

构造包含两类 gadget。

Variable Gadget ​

对每个变量 xi,构造一个 variable gadget。

这个 gadget 有一个 entrance 和一个 exit,中间放 3m+1 个顶点:

ri,0,pi,1,qi,1,ri,1,pi,2,qi,2,ri,2,…,pi,m,qi,m,ri,m

每个 clause Cj 对应中间的一对顶点:

pi,j,qi,j

具体连边可以这样做。 设这个 gadget 的 entrance 是 ai,exit 是 bi。 把上面 3m+1 个中间顶点排成一条链,相邻顶点之间加入两个方向的有向边。 再加入:

ai→ri,0,ai→ri,m,ri,m→bi,ri,0→bi

gadget 的作用是让 Hamiltonian path 在其中只有两种自然走法:

  • 从左到右走,表示 xi=true;
  • 从右到左走,表示 xi=false。

然后把所有 variable gadget 串起来:

s→a1,bi→ai+1 (1≤i<n),bn→t

所以一条从 s 到 t、经过所有 variable gadget 的 Hamiltonian path,等价于给每个变量选择 true 或 false。

Clause Gadget ​

对每个 clause Cj,新增一个 clause vertex:

cj

如果 literal xi 出现在 clause Cj 中,就在 xi 的 variable gadget 里加入一个 detour:

pi,j→cj→qi,j

这个 detour 只能在从左到右走时使用,也就是当 xi=true 时使用。

如果 literal ¬xi 出现在 clause Cj 中,就加入反方向 detour:

qi,j→cj→pi,j

这个 detour 只能在从右到左走时使用,也就是当 xi=false 时使用。

直观上:

clause vertex cj 只有在某个让 Cj 为 true 的 literal 处,才能被 Hamiltonian path 顺路访问。

构造的顶点数和边数都是 O(nm),所以可以在多项式时间内完成。

Correctness: 3SAT to Directed Hamiltonian Path ​

先证 yes instance 会变成 yes instance。

如果 ϕ 有一个 satisfying assignment,那么对每个 variable gadget:

  • 若 xi=true,就从左到右穿过 Xi;
  • 若 xi=false,就从右到左穿过 Xi。

每个 clause Cj 至少有一个 true literal。 对每个 clause,任选一个让它为 true 的 literal,路径在对应位置绕一下 detour,访问 cj。

这样路径:

  1. 从 s 走到 t;
  2. 每个 variable gadget 的中间顶点都访问一次;
  3. 每个 clause vertex cj 也通过某个 true literal 的 detour 访问一次。

所以 Gϕ 有一条 directed Hamiltonian path。

再证 no instance 会变成 no instance。

反证:假设 ϕ 是 no instance,但 Gϕ 有一条从 s 到 t 的 directed Hamiltonian path。

这条路径必须依次穿过所有 variable gadget。 在每个 variable gadget 中,它只能选择一种方向:

  • 左到右,记为 xi=true;
  • 右到左,记为 xi=false。

于是 Hamiltonian path 给出了一个变量赋值。

又因为这条路径是 Hamiltonian path,所以每个 clause vertex cj 都必须被访问。 而 cj 只能通过某个 literal 的 detour 被访问。 在 Hamiltonian path 中,这个访问必须是局部 detour:从某个 literal occurrence 的一侧进入 cj,再回到同一个 occurrence 的另一侧。 否则路径会跳到另一个 variable gadget 的中间位置,留下某段中间顶点之后无法访问。 这个 detour 能被使用,正说明对应 literal 在刚才的变量赋值下为 true。

所以每个 clause Cj 都至少有一个 true literal,ϕ 可满足。 这和 ϕ 是 no instance 矛盾。

因此:

ϕ∉3SAT⇒Gϕ∉DirectedHamiltonianPath

综上:

3SAT≤KDirectedHamiltonianPath

Step 2: Directed Hamiltonian Path to Hamiltonian Path ​

现在把有向版本 reduce 到普通的无向 Hamiltonian Path。

给定 Directed Hamiltonian Path instance:

G=(V,E),s,t

先删掉所有进入 s 的边和所有从 t 出去的边。 如果存在从 s 到 t 的 Hamiltonian path,这些边本来就不会被使用。

对每个有向图中的顶点 u,构造三个无向图顶点:

uin,umid,uout

并加入两条无向边:

uin−umid−uout

对每条有向边:

(u,v)∈E

在无向图中加入一条边:

uout−vin

得到无向图 G′。

这个构造也是多项式时间的。

Correctness: Directed to Undirected ​

先证 yes instance 会变成 yes instance。

如果原图中有 directed Hamiltonian path:

s→u1→u2→⋯→ur→t

那么在 G′ 中走:

sin,smid,sout,u1,in,u1,mid,u1,out,…,tin,tmid,tout

这是一条经过 G′ 中每个顶点一次的 Hamiltonian path。

再证 no instance 会变成 no instance。

反证:假设 G′ 有 Hamiltonian path。

注意 sin 和 tout 的 degree 都是 1,所以它们必须是整条 Hamiltonian path 的两个端点。 因为图是无向的,可以把这条 path 看成从 sin 走到 tout。

在每个 vertex gadget 里,umid 只和 uin,uout 相邻。 所以一旦 path 进入某个 gadget,就必须连续走完整个三点结构;否则 umid 之后会无法被正确访问。

又因为整条 path 从 sin 开始,第一步被迫走:

sin→smid→sout

而不同 gadget 之间的边只连接某个 uout 和某个 vin。 因此后续每次进入新 gadget 时,都会从 vin 进入,再被迫走:

vin→vmid→vout

于是整条 path 的结构只能是:

in→mid→out→in→mid→out→⋯

而 gadget 之间的边都是由原来的 directed edge 产生的:

uout−vin⟺(u,v)∈E

因此,把每个三点 gadget 收缩回一个顶点,就得到原有向图中一条从 s 到 t 的 directed Hamiltonian path。

所以如果 G′ 是 yes instance,那么原来的 Directed Hamiltonian Path instance 也是 yes instance。 等价地,no instance 会被映射成 no instance。

因此:

DirectedHamiltonianPath≤KHamiltonianPath

Conclusion ​

已经知道:

3SAT is NP-complete

并且:

3SAT≤KDirectedHamiltonianPath≤KHamiltonianPath

所以 Hamiltonian Path 是 NP-hard。

另一方面,Hamiltonian Path 在 NP 中:certificate 是一个顶点序列,verifier 只需要检查它是否每个顶点恰好出现一次,并且相邻顶点之间都有边。 这个检查可以在多项式时间内完成。

因此:

HamiltonianPath is NP-complete

Consequence of NP-completeness ​

重要定理:

如果 f 是 NP-complete,并且 f∈P,那么 P=NP。

证明:

对任意 g∈NP,因为 f 是 NP-hard,有:

g≤Kf

如果 f∈P,那么可以先把 g 的 instance polynomial-time 转成 f 的 instance,再用 f 的 polynomial-time solver 求解。

因此任意 g∈NP 都属于 P:

NP⊆P

而本来就有:

P⊆NP

所以:

P=NP

这就是为什么只要证明一个 NP-complete 问题有 polynomial-time algorithm,就会解决整个 P vs NP 问题。

NP-intermediate ​

如果:

P≠NP

Ladner's Theorem 说明:存在一些 NP 问题既不在 P 中,也不是 NP-complete。

这些问题称为 NP-intermediate。

常见候选包括:

  • Graph Isomorphism;
  • Factoring。

注意:它们只是常见候选,不等于已经证明为 NP-intermediate。

NP-hard vs NP-complete ​

NP-hard 和 NP-complete 的区别:

概念要求是否必须在 NP 中
NP-hard所有 NP 问题都能 reduce 到它不必须
NP-completeNP-hard 且自身在 NP 中必须

所以:

NP-complete=NP-hard+in NP

NP-hard 可以用于 optimization problem,例如:

  • Maximum Independent Set is NP-hard;
  • Minimum Vertex Cover is NP-hard;
  • Max-3SAT is NP-hard;
  • Finding a longest simple path is NP-hard。

这些 optimization problem 不一定本身是 decision problem,因此通常说 NP-hard,而不是直接说 NP-complete。

How to Prove a Problem Is NP-complete ​

证明一个新问题 H 是 NP-complete,常用模板是:

  1. 证明 H∈NP:
    • 给出 certificate;
    • 说明 verifier 可以 polynomial time 检查。
  2. 选择一个已知 NP-complete 问题 F。
  3. 构造 polynomial-time reduction:
F≤KH
  1. 证明 yes/no 保持一致:
x is yes for F⟺R(x) is yes for H

注意方向非常重要:

要证明 H 难,需要把已知难问题 reduce 到 H,不是把 H reduce 到已知难问题。

Take Home Messages ​

这一讲最重要的是几组定义和归约方向。

  1. P 是 polynomial time 可解的 decision problems。
  2. NP 是 yes instance 有 polynomial size certificate,并且可以 polynomial time verify 的 decision problems。
  3. P⊆NP,但是否 P=NP 仍然未知。
  4. Karp reduction f≤Kg 表示:会解 g 就会解 f,所以 g 至少和 f 一样难。
  5. SAT 是 NP-complete,这是 Cook-Levin Theorem。
  6. 通过 reduction 和传递性,可以证明 3SAT、Independent Set、Vertex Cover、Clique、Subset Sum、Hamiltonian Path 等问题都是 NP-complete。
  7. 证明 NP-complete 的标准套路是:先证明在 NP,再从一个已知 NP-complete 问题归约过来。
  8. 如果任何一个 NP-complete 问题属于 P,那么 P=NP。
  9. NP-hard 不要求问题本身在 NP 中;NP-complete 必须同时是 NP-hard 且在 NP 中。