// Stoer–Wagner min-cut for undirected weighted graphs
// Input: n, adjacency matrix or adjacency list with symmetric weights
// Here we use adjacency matrix w[n][n] (0 on diagonal), modify on contractions.
function stoerWagnerMinCut(w) {
const n = w.length;
const vertices = Array.from({length: n}, (_, i) => i);
let best = Infinity;
const used = Array(n).fill(false);
for (let phase = 0; phase < n - 1; phase++) {
const A = Array(n).fill(false);
const weights = Array(n).fill(0);
let prev = -1, sel = -1;
for (let i = 0; i < n - phase; i++) {
sel = -1;
for (let v = 0; v < n; v++) if (!used[v] && !A[v]) {
if (sel === -1 || weights[v] > weights[sel]) sel = v;
}
if (i === n - phase - 1) {
// Last added: defines a cut with previous selected node
best = Math.min(best, weights[sel]);
// Contract sel into prev
if (prev !== -1) {
for (let v = 0; v < n; v++) if (!used[v] && v !== prev) {
w[prev][v] += w[sel][v];
w[v][prev] = w[prev][v];
}
used[sel] = true;
}
break;
}
A[sel] = true; prev = sel;
for (let v = 0; v < n; v++) if (!used[v] && !A[v]) weights[v] += w[sel][v];
}
}
return best;
}
- Idea: Repeated "maximum adjacency search" phases; last two added vertices induce a min s–t cut. Contract and repeat.
- Complexity: O(n^3) with matrices; O(nm + n^2 log n) with heaps and adjacency lists.
- Output: Value of global min-cut. To recover the partition, track supernodes during contractions.