A 2-Approximation for Vertex Cover

A network operator needs to place monitoring sensors on routers. Every communication link in the network must touch at least one monitored router. This is the vertex cover problem: find a smallest set of vertices that touches every edge in a graph. It is one of the oldest and most studied Classic NP-Complete Problems. It appears in scheduling, bioinformatics, network security, and circuit testing. Yet no polynomial-time algorithm is known that finds the optimal cover. None is expected to exist. Faced with an NP-hard problem, a system builder cannot simply give up. Production systems still need an answer, and they need it fast. This is exactly the situation that motivates Approximation Algorithms and the Approximation Ratio. Instead of insisting on optimality, we design algorithms that run in polynomial time. These algorithms provably return a solution within some guaranteed factor of optimal. For vertex cover, an astonishingly short and simple algorithm exists. Repeatedly pick an edge, take both its endpoints, delete everything they touch, and repeat. This achieves a 2-approximation: it never uses more than twice the minimum possible number of vertices. What makes this algorithm a canonical teaching example is not its cleverness but its proof. The algorithm itself is almost embarrassingly naive. The insight is entirely in a matching argument. This argument lower-bounds the optimal solution using a maximal matching found along the way. This is a template that recurs throughout approximation algorithm design. Find a cheap-to-compute combinatorial object (here, a matching). Its size must provably bound the true optimum. Then show your algorithm's cost is controlled by that same object. This article gives the full algorithm and a worked trace on a concrete graph. It includes a tight example showing the factor-2 bound cannot be improved for this algorithm. It also gives the classical proof that ties everything together. It sets up key ideas: greedy selection guided by a lower-bounding witness. These ideas reappear in Metric TSP Approximation and in the broader toolkit of Heuristics and Local Search.

Key takeaways
  • Vertex cover asks for the smallest vertex set touching every edge; it is NP-hard in general.
  • The maximal-matching algorithm picks an uncovered edge, adds both endpoints to the cover, and removes all edges incident to them, repeating until no edges remain.
  • It runs in O(V+E)O(V + E) time and always outputs a valid vertex cover.
  • Its size is at most twice the optimal cover size — a genuine worst-case guarantee, not an average-case heuristic claim.
  • The proof works by showing the chosen edges form a matching, and any vertex cover must include at least one endpoint of every matching edge — separately.
  • The factor of 2 is tight: there exist graphs (e.g., complete bipartite graphs) where the algorithm's output is exactly twice optimal.
The core insight

Any maximal matching's endpoint set is simultaneously a valid vertex cover and provably at most twice as large as the smallest possible vertex cover.

The idea

A vertex cover of an undirected graph G=(V,E)G = (V, E) is a subset C⊆VC \subseteq V such that every edge (u,v)∈E(u, v) \in E has at least one endpoint in CC: that is, u∈Cu \in C or v∈Cv \in C (or both). The Vertex Cover problem asks for a vertex cover of minimum size, denoted OPT(G)\mathrm{OPT}(G). Deciding whether a graph has a vertex cover of size ≤k\le k is one of Karp's original 21 NP-complete problems, so no polynomial-time algorithm is known (or expected) to compute OPT(G)\mathrm{OPT}(G) exactly on all inputs. A matching M⊆EM \subseteq E is a set of edges no two of which share an endpoint. A matching is maximal if no edge can be added to it without breaking this property — equivalently, every edge of GG shares at least one endpoint with some edge in MM. Note the distinction from a maximum matching (largest possible matching size): a maximal matching is only "locally" un-extendable, and can be computed by a simple greedy sweep, whereas a maximum matching in general graphs requires the far more intricate blossom algorithm. The beauty of the vertex cover approximation is that it needs only a maximal matching — cheap to build — not a maximum one. The algorithm's central object is the vertex set C=⋃(u,v)∈M{u,v}C = \bigcup_{(u,v) \in M} \{u, v\}, the set of endpoints of a maximal matching MM. We will show two facts: (1) CC is always a valid vertex cover, and (2) ∣C∣≤2⋅OPT(G)|C| \le 2 \cdot \mathrm{OPT}(G). Together these establish that the algorithm computes, in polynomial time, a vertex cover at most twice the size of the smallest one — a 2-approximation algorithm in the formal sense used throughout Approximation Algorithms and the Approximation Ratio.

How it works

The algorithm processes edges one at a time, greedily growing a matching, and collects both endpoints of every matching edge into the cover. ``` VERTEX-COVER-APPROX(G = (V, E)): C ← ∅ // vertex cover under construction E' ← E // edges not yet "handled" while E' ≠ ∅: pick an arbitrary edge (u, v) ∈ E' C ← C ∪ {u, v} remove from E' every edge incident to u or to v return C ``` Each iteration picks an edge whose endpoints are not yet touched by the cover under construction — because any edge sharing an endpoint with a previously chosen edge was already deleted from E′E'. The set of edges actually chosen across the run,

M={(u,v):(u,v) was picked in some iteration},M = \{(u, v) : (u,v) \text{ was picked in some iteration}\},

is therefore a matching: no two chosen edges share an endpoint, by construction (choosing (u,v)(u,v) immediately purges every edge touching uu or vv, including any future candidate that would collide). Moreover MM is maximal: the loop only terminates when E′=∅E' = \emptyset, meaning every remaining edge of GG was deleted because it touched some already-chosen edge's endpoint — so no edge of GG can be added to MM without creating a shared endpoint. The algorithm is intentionally agnostic about which edge is picked at each step — correctness and the approximation ratio hold no matter what selection rule is used, as long as it is some uncovered edge. This robustness is part of why the algorithm is so simple to implement and reason about.

Implementation detail. To run in linear time, maintain an adjacency-list representation and a boolean array `covered[v]` marking whether vertex vv is already in CC. Iterate over the edge list once; for each edge (u,v)(u,v) with neither endpoint covered, add both to CC and mark them covered. This single pass replaces the "remove incident edges" step — an edge with a covered endpoint is implicitly skipped, without ever physically deleting it: ``` VERTEX-COVER-APPROX-LINEAR(G = (V, E)): C ← ∅ covered[v] ← false for all v ∈ V for each edge (u, v) ∈ E: // any fixed order works if covered[u] = false and covered[v] = false: C ← C ∪ {u, v} covered[u] ← true covered[v] ← true return C ```

Figure
A maximal matching (bold) and the vertex cover it induces (shaded circles)
a b c d e f g Bold edges = maximal matching M = {(a,b),(d,e)}. Shaded vertices {a,b,d,e} = cover C, |C| = 4.

Complexity & correctness

Running time. The linear-pass version examines each of the ∣E∣|E| edges exactly once, doing O(1)O(1) work per edge (two array lookups, possibly two array writes and two set insertions). Building the adjacency structure takes O(V+E)O(V + E). Total running time is

O(V+E),O(V + E),

which is optimal up to constants, since simply reading the input graph already takes Ω(V+E)\Omega(V + E) time. Space usage is O(V+E)O(V + E) for the graph plus O(V)O(V) for the `covered` array and the output set — no auxiliary data structure grows superlinearly.

Correctness — CC is a valid vertex cover. Consider any edge (x,y)∈E(x, y) \in E. If neither endpoint was ever marked covered by the time the loop reaches (x,y)(x,y), the algorithm selects it, adding both xx and yy to CC — so (x,y)(x,y) is covered. If instead the loop skips (x,y)(x,y), it is because at least one of x,yx, y was already marked covered by an earlier iteration — so again (x,y)(x,y) has an endpoint in CC. Either way every edge has an endpoint in CC; hence CC is a vertex cover of GG. This argument only used that the loop examines every edge and never un-marks a vertex, so it holds regardless of edge processing order.

The approximation guarantee — ∣C∣≤2⋅OPT(G)|C| \le 2 \cdot \mathrm{OPT}(G). Let MM be the matching consisting of exactly the edges chosen during the run (one edge per iteration of the abstract version), and let CC be the set of their endpoints, so ∣C∣=2∣M∣|C| = 2|M| since matching edges are pairwise vertex-disjoint. Claim: OPT(G)≥∣M∣\mathrm{OPT}(G) \ge |M|. Let C∗C^* be any vertex cover of GG, in particular a minimum one with ∣C∗∣=OPT(G)|C^*| = \mathrm{OPT}(G). Since MM is a matching, its edges are pairwise disjoint — no vertex belongs to two edges of MM. Because C∗C^* is a vertex cover, every edge of MM (being an edge of GG) must have at least one endpoint in C∗C^*. Assign to each edge e∈Me \in M one endpoint that lies in C∗C^* — call this a witness for ee. Because the edges of MM share no vertices, distinct edges of MM must receive distinct witnesses (the witness for ee is a vertex of ee, and no vertex belongs to two different matching edges). This gives an injective map from MM into C∗C^*, so

∣M∣≤∣C∗∣=OPT(G).|M| \le |C^*| = \mathrm{OPT}(G).

Combining the two facts:

∣C∣=2∣M∣≤2⋅OPT(G).|C| = 2|M| \le 2 \cdot \mathrm{OPT}(G).

This is exactly the definition of a 2-approximation: the algorithm's output size is at most twice the true optimum, for every input graph, not merely on average. Note the proof never needed MM to be a maximum matching — only maximal (un-extendable) — which is why the cheap greedy construction suffices; using a true maximum matching would not improve the worst-case ratio (see the tight example below) and would cost much more to compute.

Tightness of the factor 2. The bound is not an artifact of a loose proof — there are graphs on which ∣C∣|C| is exactly 2⋅OPT(G)2 \cdot \mathrm{OPT}(G). Take the complete bipartite graph Kn,nK_{n,n} with parts {u1,…,un}\{u_1,\dots,u_n\} and {v1,…,vn}\{v_1,\dots,v_n\}. A single side, say {u1,…,un}\{u_1,\dots,u_n\}, is already a vertex cover of size nn, so OPT(Kn,n)=n\mathrm{OPT}(K_{n,n}) = n. But a maximal matching in Kn,nK_{n,n} can be the perfect matching {(ui,vi)}i=1n\{(u_i, v_i)\}_{i=1}^n, giving ∣M∣=n|M| = n and ∣C∣=2n=2 OPT|C| = 2n = 2\,\mathrm{OPT}. So the analysis is asymptotically tight for this algorithm — no smarter argument will squeeze a better constant out of the maximal-matching approach itself (better ratios require fundamentally different techniques, and no polynomial algorithm with ratio strictly better than 2−ϵ2 - \epsilon for any constant ϵ>0\epsilon>0 is known, with strong evidence — resting on the Unique Games Conjecture — that none exists).

Honesty about limitations. This is a worst-case guarantee, and it can be loose in practice: on many real graphs the algorithm's output is far closer to optimal than the factor-2 bound suggests, but the algorithm offers no way to know this at runtime without also computing (or bounding) the true optimum. It also gives no control over which twice-optimal cover you get — different edge orderings can produce different CC of different sizes, all still within the factor-2 envelope. Practitioners often run several random orderings and keep the smallest resulting cover, or layer local-search improvements on top, a theme picked up in Heuristics and Local Search.

Worked example

Consider the 7-vertex graph drawn in the figure above, with vertex set {a,b,c,d,e,f,g}\{a,b,c,d,e,f,g\} and edge set

E={(a,b),(b,c),(a,c),(c,d),(d,e),(d,f),(f,g),(g,e)}.E = \{(a,b), (b,c), (a,c), (c,d), (d,e), (d,f), (f,g), (g,e)\}.

Run `VERTEX-COVER-APPROX-LINEAR` processing edges in the listed order.

StepEdge examined`covered` beforeAction`C` after
1(a,b)(a,b)none coveredboth uncovered → select{a,b}\{a,b\}
2(b,c)(b,c)bb coveredskip (an endpoint already covered){a,b}\{a,b\}
3(a,c)(a,c)aa coveredskip{a,b}\{a,b\}
4(c,d)(c,d)none coveredboth uncovered → select{a,b,c,d}\{a,b,c,d\}
5(d,e)(d,e)dd coveredskip{a,b,c,d}\{a,b,c,d\}
6(d,f)(d,f)dd coveredskip{a,b,c,d}\{a,b,c,d\}
7(f,g)(f,g)none coveredboth uncovered → select{a,b,c,d,f,g}\{a,b,c,d,f,g\}
8(g,e)(g,e)gg coveredskip{a,b,c,d,f,g}\{a,b,c,d,f,g\}

The algorithm returns C={a,b,c,d,f,g}C = \{a, b, c, d, f, g\}, size 66. (This differs from the figure's illustrative matching {(a,b),(d,e)}\{(a,b),(d,e)\} only because of edge-processing order — both are valid maximal matchings, and both yield legitimate 2-approximate covers; here the matching realized is {(a,b),(c,d),(f,g)}\{(a,b),(c,d),(f,g)\}.)

Check it is a valid cover. Every edge has an endpoint in CC: (a,b)(a,b)✓, (b,c)(b,c)✓ via b,cb,c, (a,c)(a,c)✓, (c,d)(c,d)✓, (d,e)(d,e)✓ via dd, (d,f)(d,f)✓, (f,g)(f,g)✓, (g,e)(g,e)✓ via gg. All 8 edges are covered.

Compare to the true optimum. Inspecting the graph directly: {c,d,g}\{c, d, g\} is a vertex cover — check each edge: (a,b)(a,b) needs... actually (a,b)(a,b) touches neither cc, dd, nor gg, so this fails. Trying again: the triangle {a,b,c}\{a,b,c\} forces at least 2 of its 3 vertices into any cover (a triangle's minimum cover size is 2), and separately d,e,f,gd,e,f,g form a 4-cycle, whose minimum cover size is 2 (e.g. {d,g}\{d, g\}, checking: (d,e)(d,e)✓, (d,f)(d,f)✓, (f,g)(f,g)✓, (g,e)(g,e)✓). Since the triangle and the 4-cycle share only the vertex d/cd/c connection edge (c,d)(c,d), we need a cover of the triangle, a cover of the 4-cycle, and coverage of the bridge edge (c,d)(c,d). Taking {b,c,d,g}\{b, c, d, g\}: (a,b)(a,b)✓, (b,c)(b,c)✓, (a,c)(a,c)✓, (c,d)(c,d)✓, (d,e)(d,e)✓, (d,f)(d,f)✓, (f,g)(f,g)✓, (g,e)(g,e)✓ — a valid cover of size 4. One can verify (by trying all size-3 subsets, or arguing the triangle alone needs 2 and the 4-cycle needs 2, and no vertex is shared between "the 2 triangle picks" and "the 2 cycle picks" except possibly cc or dd) that OPT(G)=4\mathrm{OPT}(G) = 4. So here the algorithm returned 66 against an optimum of 44 — a ratio of 1.51.5, comfortably inside the guaranteed factor of 22, illustrating that the worst case (Kn,nK_{n,n}-like tightness) is not always hit but is always respected as an upper bound.

Common pitfalls & traps

PitfallWhy it's wrongFix
Confusing maximal with maximum matchingA maximal matching can be much smaller than a maximum one, but the proof only needs maximality; using this loosely can lead to false claims about ratio improvementsRemember the proof's injective-witness argument only requires that MM cannot be extended, not that it is largest possible
Believing the algorithm finds a near-optimal cover in practice on all graphsThe bound is worst-case; some inputs (bipartite-like) genuinely realize a factor close to 2State the guarantee as an upper bound on the ratio, not an expected-case estimate
Trying to "fix" ties by always picking minimum-degree vertices, expecting a better ratioGreedy degree-based heuristics can perform worse than the matching algorithm on adversarial graphs, and lose the clean matching-based proof entirelyKeep the matching argument intact if you want the provable factor 2; treat degree heuristics as a separate, unproven heuristic
Forgetting to mark both endpoints coveredMarking only one endpoint breaks the matching property (chosen edges could then overlap), invalidating the injective-witness step of the proofAlways add and mark both uu and vv together in one atomic step
Assuming this generalizes to weighted vertex cover with the same ratio for freeVertex weights break the simple "∣C∣=2∣M∣|C| = 2|M|" counting argument; a different LP-rounding argument is needed for the weighted caseTreat weighted vertex cover as a related but distinct problem requiring linear-programming relaxation techniques
Off-by-one in claiming ∣C∣≤2 OPT(G)−1|C| \le 2\,\mathrm{OPT}(G) - 1 or similar tighter boundsThe Kn,nK_{n,n} tight example shows ∣C∣=2 OPT|C| = 2\,\mathrm{OPT} exactly is achievable, so no strictly-better multiplicative constant holds for this algorithmState the bound as ≤2 OPT(G)\le 2\,\mathrm{OPT}(G), and cite Kn,nK_{n,n} as evidence of tightness

Pioneers & history

The theory of NP-completeness that makes exact vertex cover intractable, and the theory of approximation that makes this algorithm meaningful, were built by a small set of foundational figures in complexity theory in the early 1970s. Vertex Cover itself appears among Richard Karp's 1972 list of 21 problems shown NP-complete by reduction, cementing it as a canonical hard problem alongside SAT and clique.

Origins · 1 minRichard M. Karp and how this was discovered
RM
Richard M. Karp
1935–present · Karp's 1972 paper "Reducibility Among Combinatorial Problems" placed Vertex Cover among the first problems proven NP-complete, establishing the very hardness that approximation algorithms are designed to work around

History
1971
Stephen Cook proves satisfiability is NP-complete, founding the theory of NP-completeness.
1972
Richard Karp's paper shows 21 problems, including Vertex Cover, are NP-complete via polynomial reductions.
1974
Early constant-factor approximation ideas for covering problems begin appearing in the algorithms literature.
1979
Garey and Johnson's compendium of NP-complete problems popularizes vertex cover as a teaching example.
2000
s: PCP-theorem-based inapproximability results and the Unique Games Conjecture sharpen exactly how close to 2 the true best-possible ratio is.

Where this matters

Vertex cover and its 2-approximation appear wherever a system must place a minimum set of "watchers," "hitters," or "testers" that touch every pairwise interaction in a network. In network security and monitoring, the algorithm models placing intrusion-detection probes on routers so every communication link passes through at least one monitored router — exactly the motivating scenario for this article. In bioinformatics, vertex cover formulations arise in phylogenetic footprinting and in finding minimal sets of genes/proteins whose removal disrupts all pairwise interactions in a protein-interaction network. In VLSI design and testing, minimum test-point placement to detect all possible faults on a circuit's connections reduces to covering problems closely related to vertex cover. The algorithm is also a standard teaching and benchmarking baseline in the theory of approximation: it is often the very first constructive 2-approximation students see with a complete, checkable proof, making it a template that recurs in the analysis of other covering and packing problems, including Metric TSP Approximation, where a different combinatorial witness (a minimum spanning tree) plays the analogous lower-bounding role. In production settings where exact solvers (integer programming, branch-and-bound) are too slow on large graphs, engineers frequently use the maximal-matching cover as a fast initial feasible solution, then refine it with local-search moves — connecting directly to the ideas in Heuristics and Local Search — while retaining the provable factor-2 ceiling as a safety guarantee if refinement runs out of time.

Ask the tutor: How does the weighted vertex cover LP-rounding algorithm achieve the same factor-2 guarantee when vertex costs differ?

Why does a maximal matching, not a maximum matching, suffice for the proof?

The proof only uses two facts about MM: its edges are pairwise vertex-disjoint (true of any matching), and the resulting endpoint set covers every edge of GG (true precisely because MM is maximal — un-extendable). Maximality is a much weaker and cheaper-to-achieve condition than maximum size: a maximal matching can be built greedily in one linear pass, while a maximum matching requires sophisticated algorithms like Edmonds' blossom algorithm running in polynomial but much higher-degree time. Since the approximation ratio proof goes through with only maximality, there is no benefit — for this particular algorithm's provable guarantee — to paying the extra cost of finding a maximum matching. Interestingly, the tight example (Kn,nK_{n,n}) uses a matching that happens to be both maximal and maximum, showing that even the strongest matching does not break the factor-2 ceiling.

Is 2 the best approximation ratio known for Vertex Cover?

Among this specific simple algorithm's guarantees, yes — 2 is both achieved and tight, as the complete bipartite graph example shows. Across all known polynomial-time algorithms for general graphs, ratios only marginally below 2 (of the form 2−Θ(1/log⁡n)2 - \Theta(1/\sqrt{\log n})) have been achieved using semidefinite programming, and no efficient algorithm is known to beat 2 by a constant factor. Under the Unique Games Conjecture, a widely believed but unproven complexity assumption, it can be shown that no polynomial-time algorithm can achieve ratio 2−ϵ2 - \epsilon for any fixed ϵ>0\epsilon > 0 unless a major complexity collapse occurs. So the maximal-matching algorithm is remarkably close to the frontier of what is theoretically possible, despite its simplicity.

Does the algorithm's output depend on which edge is picked first?

Yes — different edge orderings can produce different vertex covers of different sizes, though all are guaranteed to be within a factor of 2 of optimal. In the worked example, processing edges in a different order could have produced the matching {(a,c),(d,e),(f,g)}\{(a,c), (d,e), (f,g)\} or other combinations, yielding a cover of size 6 or possibly different composition. This order-dependence means the algorithm is not deterministic in its output size (only in its worst-case bound), so practical implementations sometimes try multiple random orderings and keep the smallest resulting cover, trading extra runtime for a possibly smaller — but still only empirically, not provably, better — answer.

How does this relate to the general theory of NP-hardness and approximation?

Vertex Cover is NP-complete, meaning no polynomial-time algorithm is known (or believed likely) to solve it exactly on all instances, a fact established via reductions studied under Classic NP-Complete Problems. Approximation algorithms sidestep this impossibility by relaxing the requirement from "always optimal" to "always within a guaranteed factor of optimal, in polynomial time." This vertex cover algorithm is a flagship example of the technique from Approximation Algorithms and the Approximation Ratio: rather than attacking the NP-hard optimization directly, it constructs an easy-to-compute combinatorial witness (the matching) whose size is provably sandwiched between the algorithm's output and the true optimum, converting an intractable exact problem into a tractable approximate one with a certified quality guarantee.

Can this algorithm be adapted for weighted vertex cover, where vertices have costs?

Not directly with the same simple argument and the same ratio guarantee via this exact construction. In weighted vertex cover, each vertex vv has a cost w(v)w(v), and the goal is to minimize total cost while covering all edges; the matching-endpoint trick no longer directly bounds cost because two matched vertices could have wildly different weights, breaking the clean "∣C∣=2∣M∣|C| = 2|M|" counting step. The standard 2-approximation for the weighted case instead uses linear programming relaxation and rounding: solve the LP relaxation of the covering constraints, then include vertex vv in the cover if its LP value is at least 1/21/2. That rounding technique, while related in spirit (again exploiting a bound between a relaxed lower bound and the algorithm's output), is a distinct technique from the maximal-matching argument shown here.

What is the relationship between vertex cover and independent set?

A set S⊆VS \subseteq V is an independent set (no two vertices in SS are adjacent) if and only if its complement V∖SV \setminus S is a vertex cover — this is a direct consequence of the definitions, since an edge fails to be "covered" by SS's complement exactly when both its endpoints are in SS, which independence forbids. This means minimizing vertex cover size is equivalent to maximizing independent set size: OPTVC(G)=∣V∣−OPTIS(G)\mathrm{OPT}_{\text{VC}}(G) = |V| - \mathrm{OPT}_{\text{IS}}(G). However, this duality does not transfer approximation guarantees: a 2-approximation for vertex cover does not imply any nontrivial approximation for maximum independent set, because the additive relationship ∣V∣−∣S∣|V| - |S| does not preserve multiplicative ratios — independent set is in fact one of the hardest problems to approximate, with no constant-factor approximation known or believed to exist.

Does this algorithm work on directed graphs or hypergraphs?

As stated, the algorithm and its proof are specific to simple undirected graphs. For directed graphs, "vertex cover" is typically not the natural generalization; instead concepts like feedback vertex sets are used, which require entirely different algorithmic techniques. For hypergraphs, where an edge can connect more than two vertices, the direct analog is the hitting set or set cover problem, and the matching-based argument degrades: a maximal matching in a kk-uniform hypergraph only gives a kk-approximation via the same style of argument (each hyperedge has up to kk vertices, so at most kk hyperedges' witnesses can collide at one vertex), not the tight factor of 2 achieved here for ordinary graphs.

Before this

Where this leads