# Playing out under a press: the safest route isn't the shortest

Source: https://www.footballdatascience.co.uk/learn/routes-through-the-press
Published: 2026-10-01

> The opposition presses high and every pass is a risk. Treat the team as a network, with each passing lane carrying its chance of getting through, and the safest way from keeper to striker turns out to be three passes, not one. Dijkstra's method finds it, and shows which lane the press should aim at.

**On the terraces:** Under a high press, the long ball is the shortest route and often the worst. This piece shows why three short passes can be safer than one long one, and which pass the press should aim to cut out.

## The football question

The opposition presses high. The keeper has the ball and the aim is simple: get it to the striker. He can go long, one pass that's often lost, or play out through the defenders, more passes but each one safer. **Which route gives the best chance of getting the ball there?**

## The concept

A team in possession can be drawn as a **network** (mathematicians say a *graph*): the players are points and the passing lanes are links between them. [Linear Algebra #10](/learn/passing-networks) counted how often the ball travelled along each link. Here each link carries something else: the chance a pass along it gets through the press.

A route is a chain of links from the keeper to the striker, and the ball only arrives if every pass on it is completed. Finding the best route through a network is a **shortest path** problem. "Shortest" here doesn't mean fewest passes: it means the route with the best value, here the highest chance of arriving.

## A football example

Take the same made-up five-a-side team as Linear Algebra #10: keeper, defender, a left-sided and a right-sided player, and a striker. Against a high press, each pass gets through with a made-up chance: the keeper's short ball to the defender 90% of the time, his long ball to the striker only 30%.

<figure class="rank-chart">
<div role="img" aria-label="A network of five players. Keeper at the bottom, defender above him, left and right players either side, striker at the top. Each forward passing lane is labelled with its completion chance against the press. The safest route, keeper to defender 90%, defender to right 85%, right to striker 65%, is highlighted; it gets through 49.7% of the time. The direct ball from keeper to striker, 30%, is dashed.">

</div>
<figcaption>The forward passing lanes and their chance of beating the press, made up. Some sideways and backward lanes are left off the picture but used in the sums. Green is the safest route to the striker; gold is the direct ball.</figcaption>
</figure>

A route's chance is every pass's chance multiplied together:

$$\text{chance of arriving} = p_1 \times p_2 \times \dots \times p_n$$

<div class="plain" markdown="1">
In plain football

- **p₁, p₂, …** are the chances of each pass on the route getting through.
- The ball only arrives if they all get through, so the chances multiply. Every extra pass, however safe, makes the total a little smaller.
- So a longer route only wins if its passes are much safer than the short route's.
</div>

## Shortest isn't safest

There are 16 routes from the keeper to the striker that don't involve the same player twice. The best five, and the long ball:

| Route | Passes | Gets there |
|---|---|---|
| Keeper, defender, right, striker | 3 | 49.7% |
| Keeper, defender, left, striker | 3 | 43.2% |
| Keeper, right, striker | 2 | 42.3% |
| Keeper, left, striker | 2 | 42.0% |
| Keeper, left, defender, right, striker | 4 | 32.9% |
| Keeper to striker, long | 1 | 30.0% |

The long ball is the **fewest passes and the worst** of these. Playing out through the defender and the right-sided player takes three passes and gets through **49.7%** of the time: 0.90 × 0.85 × 0.65. The two-pass routes lose out because the keeper's passes out wide are riskier than his short ball to the defender.

## Dijkstra's method

Listing every route works for five players. For eleven, with a lane between every pair, there are 986,410 routes from keeper to striker, and real networks with more points have far more. The standard method is **Dijkstra's**, designed by the Dutch computer scientist Edsger Dijkstra in 1956, in his own account "in about twenty minutes" at a café in Amsterdam, and published in 1959.

It needs adding, not multiplying, so each pass gets a **cost** of minus its logarithm:

$$\text{cost of a pass} = -\log p$$

<div class="plain" markdown="1">
In plain football

- A sure pass (p = 1) costs 0. A riskier pass costs more: 0.90 costs 0.11, 0.30 costs 1.20.
- Logarithms turn multiplying into adding, so the route with the **lowest total cost** is the route with the **highest chance of arriving**.
- Every cost is zero or more, which is what Dijkstra's method needs.
</div>

Then Dijkstra's method works outwards from the keeper, always settling the player who can be reached most cheaply so far, and never needing to look back at a player once he's settled. When it settles the striker, the route it used is the best one. It finds the same route as the full list: **keeper, defender, right, striker, 49.7%**.

## Where the press should aim

A pressing coach is asking the opposite question: which lane, if we shut it, hurts them most? Shut each lane of the safest route in turn and find the next best:

| Lane shut | New best route | Gets there |
|---|---|---|
| Keeper to defender | Keeper, right, striker | 42.3% |
| Defender to right | Keeper, defender, left, striker | 43.2% |
| Right to striker | Keeper, defender, left, striker | 43.2% |

Shutting the **keeper's pass to the defender** costs the most, 7.5 percentage points, because it's the first link of both of the two best routes. That's the network's way of saying what pressing coaches know already: stop the first pass and the whole build-up has to change. For the team playing out, it says where an extra short option, a midfielder dropping in, would be worth most.

## Why it matters

Networks are everywhere in football: passes between players, scouts' journeys, travel between away games. Asking for the best route, and for the link whose loss hurts most, turns a picture of the team into decisions: how to play out, where to press, where to add an option. And the lesson of the long ball carries over: fewer steps isn't the same as better odds. [Part 9](/learn/fixture-congestion-rotation) turns to scheduling: rotating a squad through a run of fixtures.

## Limitations

- **The chances are made up.** Real completion rates under a press come from event or tracking data, which ours doesn't have.
- **Passes aren't independent.** One good pass can leave the next player more space, so multiplying chances is an approximation.
- **The press moves.** Opponents shift as the ball moves, so a lane's chance changes during the move. A fixed network is a snapshot.
- **Arriving isn't scoring.** The best route to the striker isn't necessarily the best route to a goal; that would need values for what happens when the ball arrives.

## Try it yourself

The pressing team pushes its striker onto the keeper, and his short pass to the defender drops from 90% to 70%. Before running the code, guess: is playing out still better than going long, and which route is safest now?

## Reproduce the analysis

Plain Python, nothing to install or download. It lists every route, runs Dijkstra's method, and shuts each lane of the best route in turn. All the numbers are made up.

```python
import heapq
from math import exp, log

# Made up: the chance each pass is completed against a high press, for the five-a-side team of Linear Algebra #10.
# K keeper, D defender, L left, R right, S striker.
lanes = {("K", "D"): 0.90, ("K", "L"): 0.70, ("K", "R"): 0.65, ("K", "S"): 0.30,
         ("D", "K"): 0.95, ("D", "L"): 0.80, ("D", "R"): 0.85, ("D", "S"): 0.35,
         ("L", "D"): 0.85, ("L", "R"): 0.70, ("L", "S"): 0.60,
         ("R", "D"): 0.85, ("R", "L"): 0.70, ("R", "S"): 0.65}


def chance(route, lanes):
    """The chance every pass on a route is completed: multiply them."""
    p = 1.0
    for a, b in zip(route, route[1:]):
        p *= lanes[a, b]
    return p


def every_route(lanes, start="K", end="S"):
    """List every route that doesn't visit a player twice."""
    found, stack = [], [[start]]
    while stack:
        route = stack.pop()
        if route[-1] == end:
            found.append(route)
            continue
        stack += [route + [b] for (a, b) in lanes if a == route[-1] and b not in route]
    return found


def dijkstra(lanes, start="K", end="S"):
    """Safest route. A pass completed with chance p costs -log(p): multiplying chances becomes adding costs, and the
    cheapest route is the safest. Dijkstra's method settles the nearest player first and never looks back."""
    best, queue = {start: 0.0}, [(0.0, [start])]
    while queue:
        cost, route = heapq.heappop(queue)
        here = route[-1]
        if here == end:
            return route, exp(-cost)
        if cost > best.get(here, float("inf")):
            continue
        for (a, b), p in lanes.items():
            if a == here and cost - log(p) < best.get(b, float("inf")):
                best[b] = cost - log(p)
                heapq.heappush(queue, (best[b], route + [b]))
    return None, 0.0


routes = every_route(lanes)
print(f"{len(routes)} routes from keeper to striker; the five safest:")
for r in sorted(routes, key=lambda r: -chance(r, lanes))[:5]:
    print(f"  {'-'.join(r):<10} {len(r) - 1} passes, {chance(r, lanes):.1%}")
print(f"  Direct, K-S: 1 pass, {lanes['K', 'S']:.1%}")
route, p = dijkstra(lanes)
print(f"Dijkstra's method: {'-'.join(route)}, {p:.1%}")

print("\nIf the press shuts one lane of that route:")
for a, b in zip(route, route[1:]):
    open_lanes = {k: v for k, v in lanes.items() if k != (a, b)}
    r2, p2 = dijkstra(open_lanes)
    print(f"  {a}-{b} shut: best is {'-'.join(r2)}, {p2:.1%} ({(p2 - p) * 100:+.1f} percentage points)")
```

It prints:

```text
16 routes from keeper to striker; the five safest:
  K-D-R-S    3 passes, 49.7%
  K-D-L-S    3 passes, 43.2%
  K-R-S      2 passes, 42.3%
  K-L-S      2 passes, 42.0%
  K-L-D-R-S  4 passes, 32.9%
  Direct, K-S: 1 pass, 30.0%
Dijkstra's method: K-D-R-S, 49.7%

If the press shuts one lane of that route:
  K-D shut: best is K-R-S, 42.3% (-7.5 percentage points)
  D-R shut: best is K-D-L-S, 43.2% (-6.5 percentage points)
  R-S shut: best is K-D-L-S, 43.2% (-6.5 percentage points)
```

The logarithm trick is why the snippet uses `exp` at the end: it turns Dijkstra's lowest total cost back into a chance.

## Further reading

- [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm), Wikipedia. The method, its history and Dijkstra's own account.
- [Shortest path problem](https://en.wikipedia.org/wiki/Shortest_path_problem), Wikipedia. The problem in general and the other methods for it.
