COM­P4804: Al­go­rithms II
$\new­com­mand{\R}{\mathbb{R}}\De­clar­e­Math­Op­er­a­tor{\E}{\mathbf{E}}\De­clar­e­Math­Op­er­a­tor{\deg}{deg}$
Fixed-Pa­ra­me­ter Tractable Al­go­rithms

Let $G=(V,E)$ be a (sim­ple undi­rected) graph with $n$ ver­tices and $m$ edges. We say that a set $C\sub­seteq V$ is a ver­tex-cover of $G$ if, for every edge $uw\in E$, at least one of $u$ or $w$ is in $C$. The Ver­tex-Cover prob­lem is:

The Ver­tex-Cover prob­lem is NP-com­plete, so we won't find a poly­no­mial-time al­go­rithm that solves it ex­actly. In­stead, we'll set­tle for an al­go­rithm that is fast when $k$ is small

Ex­er­cise: Find a al­go­rithm for Ver­tex-Cover with run­ning time $O(n^{k+1})$.

That's an easy ex­er­cise—just enu­mer­ate all $\binom{n}{k}$ sub­sets of ver­tices of size $k$ and test each one to see if it's a ver­tex cover. Let's aim for some­thing bet­ter: An al­go­rithm whose run­ning time is $O(n\times 2^k)$ (in­stead of the $O(n\times n^k))$ that the ex­er­cise asks for.

A sim­ple FPT al­go­rithm for Ver­tex-Cover

We start with the fol­low­ing sim­ple ob­ser­va­tion (which is ac­tu­ally just the de­f­i­n­i­tion of a ver­tex-cover):

Ob­ser­va­tion 1: For each edge $uw$ of $G$, any ver­tex-cover of $G$ con­tains at least one of $u$ or $w$.

This ob­ser­va­tion is the basis of a re­cur­sive al­go­rithm for Ver­tex-Cover that makes only two re­cur­sive calls per in­vo­ca­tion:

  1. Ver­tex­Cov­erFPT$(G, k)$
    1. if $G$ has no edges then re­turn true
    2. if $k=0$ then re­turn false
    3. let $uw$ be some edge of $G$
    4. if Ver­tex­Cov­erFPT$(G-u, k-1)$ then re­turn true
    5. if Ver­tex­Cov­erFPT$(G-w, k-1)$ then re­turn true
    6. re­turn false

This al­go­rithm is clearly cor­rect when $k=0$. To prove that it's cor­rect for $k>0$ we can use in­duc­tion and Ob­ser­va­tion 1: If $G$ has a ver­tex-cover $C$ of size $k$, then this cover con­tains at least one of $u$ or $w$. If $C$ con­tains $u$, then the first re­cur­sive call will re­turn true. If $C$ con­tains $w$ (but not $u$) then the sec­ond re­cur­sive call will re­turn true. Oth­er­wise, if $G$ has no ver­tex cover of size $k$ then the al­go­rithm re­turns false.

Using the right rep­re­sen­ta­tion of the graph $G$, it's fairly easy to im­ple­ment this al­go­rithm so that each re­cur­sive in­vo­ca­tion runs in $O(n)$ time. To un­der­stand the total run­ning-time (in­clud­ing all re­cur­sive in­vo­ca­tions) we need only to no­tice that the re­cur­sion tree is a com­plete bi­nary tree of height $k$, so it has $2^k$ leaves and $2^{k-1}$ in­ter­nal nodes, each of which con­tributes $O(n)$ to the run­ning time fo the al­go­rithm, so the over­all run­ning-time is \[ (2^k + 2^k-1)\times O(n) = O(n\times 2^k) \en­space . \]

The­o­rem 1: There is an al­go­rithm for Ver­tex-Cover that has run­ning-time $O(n\times 2^k)$.

The­o­rem 1 is nice. For ex­am­ple, if $k=10$ and $n=1,000,000$, then the run­ning-time of the al­go­rithm is on the order of 1,000,000,000. This would take maybe a few sec­onds on a mod­ern com­puter. Now let's see if we can do bet­ter still.

Ker­nel­iza­tion

The idea be­hind ker­nel­iza­tion is that we can pre­process $G$ using a fast (poly­no­mial-time) al­go­rithm to make it smaller, be­fore we call Ver­tex­Cov­erFPT. It's based on a cou­ple of sim­ple ob­ser­va­tions:

Ob­ser­va­tion 2: If $G$ has a ver­tex $u$ of de­gree greater than $k$ and $C$ is a ver­tex-cover of $G$ with $|C|\le k$, then $u\in C$.

Proof: If $C$ doesn't in­clude $u$ then it has to in­clude all its neigh­bours, but $u$ has more than $k$ neigh­bours. ∍

So, let $C_0$ be the sub­set of ver­tices in $G$ that have de­gree greater than $k$. Then $G$ has a ver­tex-cover of size at most $k$ if and only if $G'=G-C_0$ has a ver­tex-cover of size at most $k'=k-|C_0|$. Now, the graph $G'$ is in­ter­est­ing, be­cause it has no ver­tex of de­gree greater than $k$.

Lemma: If $G'$ has more than $kk'$ edges then $G'$ has no ver­tex cover of size $k'$.

Proof: Each ver­tex of $G'$ can cover at most $k$ edges so we cer­tainly can't cover more than $kk'$ edges using only $k'$ ver­tices. ∍

Fi­nally, let $G''$ be the graph that we get when we re­move iso­lated ver­tices from $G'$, and we run Ver­tex­Cov­erFPT$(G'',k-|C_0|)$. To sum­ma­rize:

  1. Let $C_0$ be the ver­tices of $G$ of de­gree greater than $k$
  2. If $|C_0|>k$ then re­turn false
  3. Let $G'=G-C_0$ and let $k'=k-|C_0|$
  4. If $G'$ has more than $kk'$ edges then re­turn false
  5. Let $G''$ be ob­tained by re­mov­ing iso­lated ver­tices from $G$
  6. re­turn Ver­tex­Cov­erFPT$(G'',k-|C_0|)$

Ex­cept for the Step 6, each of these steps can be im­ple­mented in $O(n+m)$ time. Now, the graph $G''$ has no iso­lated ver­tices and at most $kk'\le k^2$ edges, so it has at most $2k^2$ ver­tices. There­fore, Step 6 runs in time $O(k^2\times 2^k)$ time.

The­o­rem 2: There is an al­go­rithm for Ver­tex-Cover that has run­ning-time $O(n+m+k^22^k)$.

This al­go­rithm is ex­po­nen­tial, but only in $k$. It can han­dle big graphs, it's only lim­ited by the value of $k$. It could, for ex­am­ple, eas­ily han­dle a graph with 400 mil­lion edges and $k=20$.