JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Parameterized Complexity and FPT

NP-hardness says a problem is hard, but it rarely says WHERE the hardness lives. Parameterized complexity finds a small dial k inside the problem and quarantines the explosion to a factor f(k), leaving the dependence on input size polynomial — and we prove exactly why vertex cover yields to it.

A second dial besides n

By now you have met three honest responses to an NP-hard problem. The complexity rung taught you that NP-completeness means no polynomial algorithm is known — never that none exists — so we cope rather than surrender. The approximation rung traded exactness for a provable factor. This rung's earlier guides traded full information for a tiny window: an online algorithm decides without the future, a streaming sketch decides without the whole input. Parameterized complexity trades along a different axis entirely: it keeps the exact answer and the whole input, but asks a sharper question about where the difficulty actually hides.

The key insight is that one number, the input size n, is a blunt instrument. Two graphs with the same n can be worlds apart in difficulty. So we introduce a second dial, a parameter k, chosen to capture the structure that makes an instance hard. For finding a small vertex cover — a set of vertices touching every edge — the natural dial is the cover size k itself: in practice you often only care whether a tiny cover exists (say k = 10) even though the graph has millions of vertices. The question stops being "how hard is vertex cover?" and becomes "how hard is vertex cover when k is small?"

Why does that question have a different answer? Because a slow algorithm can be slow in two very different ways. Brute force tries all subsets of size k — there are about n^k of them, and that n^k is fatal: even k = 10 on a million-vertex graph is a million-to-the-tenth, hopeless. The whole game of this guide is to move that explosion off of n and onto k alone — to pay 2^k instead of n^k. When the exponent rides on the small dial instead of the big one, a problem that looked impossible becomes routine.

The definition: where the exponent rides

A parameterized problem is fixed-parameter tractableFPT — if it can be solved in time f(k) * n^c, where n is the input size, k is the chosen parameter, c is a constant that does not depend on k, and f is any function of k alone — it may grow as wildly as 2^k or even 2^(2^k). The entire content of the definition is one word: separation. The unavoidable exponential is quarantined inside f(k), where it multiplies, and is forbidden from entering the exponent of n. Read the two shapes side by side and the difference is the whole subject.

Put the two shapes against real numbers. Take k = 10 on a graph with n = 1,000,000. The FPT shape 2^k * n is 1024 * 1,000,000, about 10^9 — a fraction of a second. The brute-force shape n^k is (10^6)^10 = 10^60 — heat-death-of-the-universe time. The arithmetic is the whole moral: in 2^k * n the exponent rides on the small dial k, so once k is fixed f(k) is just a constant out front; in n^k the parameter has climbed into the exponent of n itself, so even k = 10 is hopeless on a large graph. FPT insists the exponent ride on k and never on n.

Notice that 2^k * n and n^k are both "exponential," yet for a small k on a large graph they differ by fifty orders of magnitude. That is the prize FPT chases — and it is a genuinely different prize from the approximation rung. There, on vertex cover, we accepted a cover up to twice optimal but ran in polynomial time on every instance. Here we demand the exact minimum cover, but only promise efficiency when k is small. Two coping strategies, two different sacrifices: approximation gives up accuracy to keep speed everywhere; FPT keeps accuracy and confines the cost to a parameter you hope is small.

The bounded search tree: vertex cover in 2^k * n

Here is the algorithm that makes it concrete, and it rests on one tiny, undeniable observation. Pick any edge (u, v) in the graph. A vertex cover must touch this edge, so it must contain u, or v, or both — there is no fourth option. That single forced choice is the lever. We branch: try "u is in the cover" in one direction and "v is in the cover" in the other. Whichever branch we take, we have committed one vertex to the cover and may delete it (and its edges) from the graph, leaving a smaller subproblem in which we now seek a cover of size k - 1. This is a focused cousin of branch and bound — branch on a forced choice, recurse on a strictly smaller budget.

VC(G, k):
  if G has no edges:  return YES        # everything covered
  if k == 0:          return NO          # edges left but no budget
  pick any edge (u, v)
  return VC(G - u, k-1)  OR  VC(G - v, k-1)   # branch: u in, or v in
Each call spends one unit of budget and recurses twice, so the search tree has depth at most k and at most 2^k leaves; each node does O(n) work to find an edge and delete a vertex.

Now count the cost, because this is where the magic becomes arithmetic. Every recursive call drops k by exactly 1, so no path of recursion is longer than k steps — the search tree has depth at most k. Each node branches in two, so the tree has at most 2^k leaves and about 2^k nodes total. At each node we do only cheap work: scan for an edge, delete a vertex, all in O(n) time. Multiply, and the whole search costs O(2^k * n). The exponent rides on k, exactly as the definition demands. Vertex cover is the poster child of FPT precisely because this proof is so short.

Kernelization: shrink first, then brute force

There is a second, complementary route to FPT, and it matches what every experienced solver does by instinct: before thinking hard, cross off the parts that are forced. Kernelization turns that instinct into a theorem. It is a polynomial-time preprocessing step that shrinks any instance down to an equivalent one — same yes/no answer — whose size is bounded by a function of k alone, no matter how huge the original was. The shrunken instance is called the kernel, and the work is done by reduction rules: simple simplifications you must prove are safe, then apply until nothing changes.

  1. Rule 1 (isolated vertices): delete any vertex with no edges. It covers nothing, so it can never help a cover — removing it changes no answer and shrinks the graph.
  2. Rule 2 (high-degree vertices): if a vertex v has more than k neighbours, it MUST be in every size-k cover. If you left it out, all its k+1-plus edges would each need a different cover vertex — already more than k. So put v in the cover and decrease k by 1.
  3. Apply both repeatedly until neither fires. Now every surviving vertex has degree at most k, and a size-k cover touches at most k * k = k^2 edges. So if more than k^2 edges remain, immediately answer NO; otherwise you hold a kernel of at most k^2 edges.

Look at what just happened: a graph with a million edges was reduced, in polynomial time, to one with at most k^2 — its size now depends only on k. Run any exact method on the kernel (even the 2^k search tree, but now on a tiny input) and you are done. And there is a beautiful theorem closing the loop: a parameterized problem is FPT if and only if it has a kernelization. So the two routes of this guide are not rivals but two faces of one coin — kernels and fixed-parameter tractability are equivalent, and a smaller kernel means faster solving.

Treewidth, exact exponential cousins, and the wall

Solution size is the most obvious dial, but it is not the only one — and one of the deepest is structural. Many problems that are NP-hard on general graphs are easy on trees, because a tree has no tangled cycles: you sweep from the leaves to the root, combining sub-answers, exactly the tree dynamic programming you already know. Treewidth is a single number measuring how far a graph is from being a tree — 0 or 1 for actual trees, small for nearly-tree-like graphs, large for densely woven ones. Bound the treewidth t and you can run DP over a tree decomposition, remembering a partial answer for every behaviour of the few vertices in each small "bag," giving running times shaped like f(t) * n.

Notice the same FPT shape, now with t in the role of k: the exponential cost lives in f(t) (often around 2^t per bag), and the dependence on n stays linear. This is why so much real structure pays off — control-flow graphs of structured code, series-parallel networks, and many real-world graphs have small treewidth, and a vast catalogue of otherwise-hard properties (independent set, dominating set, coloring) becomes tractable on them. It is the same trick as the search tree, viewed through structure instead of solution size: find a parameter that is small in practice, and pay the exponential only in that.

FPT is a close relative of the exact exponential mindset: both refuse to give up the optimum and instead fight the exponential's shape. Held-Karp solves TSP in O(2^n * n^2) — astronomically better than n! — and branch-and-reduce can solve independent set in about 1.2^n. The difference is the axis of attack: exact exponential algorithms lower the base of an n-exponential (2^n down toward 1.3^n), while FPT moves the exponent off n entirely and onto a parameter k. Same refusal to lose accuracy, two different ways to make the unavoidable explosion survivable.

Finally, the honest wall. Not every parameterized problem is FPT. Finding a clique of size k looks deceptively similar to vertex cover, yet the best known algorithms still take roughly n^k — the exponent stubbornly clings to n. Parameterized complexity has its own hardness theory, the W-hierarchy, that classifies such problems as likely-not-FPT, just as NP-completeness classifies likely-not-polynomial. So "choose a parameter and you win" is false; the parameter must be the right one, and even then some problems resist. And remember f(k) can be 2^(2^k) — still "FPT" by the definition, yet useless in practice. FPT gives a finer, more honest map of difficulty than "P versus NP-hard," but like every tool in this rung, it earns its power only when its assumption — a genuinely small parameter — actually holds.