NeFut Logo NeFut
Admin Login

Comprehensive Analysis of All-Pairs Shortest Path Algorithms and Bitset State Compression Optimization

Published at: 2026-05-27 09:17 Last updated: 2026-06-06 13:04
#algorithm #Dynamic Programming #Bitset

Core Logic and Mathematical Principles

The goal of All-Pairs Shortest Paths (APSP) is to find the shortest path between any two points $u, v \in V$ in a graph. To address this problem, the Floyd-Warshall algorithm demonstrates an extremely concise matrix algebra essence under the framework of dynamic programming. Additionally, in unweighted graphs or transitive closure problems, combining Bitset state compression can push the algorithm's constants to physical limits.

1. Matrix Incremental Paradigm: Floyd-Warshall Algorithm

The essence of the Floyd algorithm is the dynamic introduction of topological intermediate nodes.

2. Transitive Closure and Bitset State Compression

In the connectivity determination problem of directed graphs (transitive closure), we are only concerned with whether $i$ can reach $j$, and the state matrix degenerates to a Boolean matrix $f[i][j] \in \{0, 1\}$.


Algorithm Derivation and State Design

1. Floyd-Warshall State Transition Equation

Define $d[i][j]$ as a two-dimensional matrix storing distances. In the $k^{th}$ iteration, for any node pair $(i, j)$, the state transition equation is:

$$d[i][j] = \min(d[i][j], d[i][k] + d[k][j])$$

Physical Boundaries: At initialization, if $i == j$, then $d[i][j] = 0$; if there is a direct edge, then $d[i][j] = w(i, j)$; all other cases are marked as $\infty$. Strict Mathematical Constraint on Loop Order: The stage variable $k$ must be the outermost loop. This is because the state of $f[k][i][j]$ is strongly dependent on the fully matured state of the $f[k-1]$ stage. If $k$ is placed in the inner loop, the state transition occurs before the intermediate point is fully prepared, leading to a breakdown in the topological recursion chain.

2. Bitset Transitive Closure Transition Equation

Define std::bitset<MAXN> g[MAXN], where g[i][j] indicates whether $i$ can reach $j$. When the outer loop control variable $k$ is established:

$$\text{if } (g[i][k]) \quad g[i] \mid= g[k]$$

Physical Meaning: If $i$ can reach $k$, then all points that $k$ can reach are also reachable by $i$. The entire row is directly processed through bitwise OR operations.


C++ Standard Source Code (Bitset Optimized Transitive Closure Industrial Template)

#include <iostream>
#include <vector>
#include <bitset>
#include <algorithm>

const int MAXN = 2005; // Design for graph connectivity with N <= 2000

// Use bitset to compress the adjacency matrix and reachability matrix
std::bitset<MAXN> g[MAXN]; 

void transitive_closure(int n) {
    // Prevent fatal low-level errors: k must be the outermost loop, which is the core of stage driving
    for (int k = 1; k <= n; ++k) {
        for (int i = 1; i <= n; ++i) {
            // Key constant optimization: only when i can actually reach k does the whole row bit operation make sense
            if (g[i][k]) {
                g[i] |= g[k]; // Single machine instruction processes the state transition of 64 points in parallel
            }
        }
    }
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    int n, m;
    if (!(std::cin >> n >> m)) return 0;

    // Self-loop initialization
    for (int i = 1; i <= n; ++i) {
        g[i].set(i); // g[i][i] = 1
    }

    for (int i = 0; i < m; ++i) {
        int u, v;
        std::cin >> u >> v;
        g[u].set(v); // Establish directed edge, g[u][v] = 1
    }

    transitive_closure(n);

    // Output the final reachability matrix (0/1 connectivity state)
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            std::cout << (g[i][j] ? 1 : 0) << (j == n ? "" : " ");
        }
        std::cout << "\n";
    }

    return 0;
}

NOIP Practical Pitfall Guide

  1. Floyd Algorithm Loop Order Reversal: A very common and low-level error is writing the loops as for(i...) for(j...) for(k...). This writing relies on d[i][k] and d[k][j] in the inner updates, which may not have been fully relaxed yet, and they may still be initialized as $\infty$. This directly leads to missed calculations, and the shortest path obtained due to topological breaks may be larger than the true value. It is imperative to enforce that k is the outermost loop.
  2. Floyd Initialization Not Intercepting Multiple Edges: During the graph input phase, if the data provided by the problem contains multiple edges (i.e., multiple different edges between the same two points), if the contestant directly writes d[u][v] = w, it will cause subsequent readings of larger weighted multiple edges to overwrite previously read shorter edges. The standard input must be written as d[u][v] = \min(d[u][v], w).

Classic NOIP/Luogu Problems

1. Luogu P1119 Post-Disaster Reconstruction

2. Luogu P2419 [USACO08JAN] Cow Contest S

Original Source: local://10.4

[h] Back to Home