Number of Possible Sets of Closing Branches — Solution
Number of Possible Sets of Closing Branches solution explained: step-by-step approach, complexity and code in Python, Java, C++ and JavaScript.
Number of Possible Sets of Closing Branches is a hard coding problem on bit manipulation, graph and heap, asked in Amazon and Google interviews.
- Difficulty: Hard
- Topics: Bit Manipulation, Graph, Heap, Enumeration, Shortest Path
- Asked at: Amazon, Google
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
A company has n branches numbered 0 to n - 1, linked by two-way roads: roads[i] = [u, v, w] is a road of length w between branches u and v. There may be several roads between the same two branches.
The company wants to close some set of branches (possibly none, possibly all). After closing, the branches still open must all be within maxDistance of each other, travelling only through open branches. Closed branches and the roads touching them can no longer be used.
Return the number of possible sets of branches to close such that every pair of open branches is at distance at most maxDistance.
Example 1
Input: n = 3, maxDistance = 5, roads = [[0,1,2],[1,2,10],[0,2,10]]
Output: 5
Explanation: Valid closings: {0,1,2} (nothing open), {0,1} and {1,2} and {0,2} (one branch open), and {2} (0 and 1 open, 2 apart). Keeping 2 open with another branch puts them 10 apart.
Example 2
Input: n = 3, maxDistance = 5, roads = [[0,1,20],[0,1,10],[1,2,2],[0,2,2]]
Output: 7
Explanation: Every closing works except closing only {2}: then 0 and 1 are 10 apart.
Example 3
Input: n = 1, maxDistance = 10, roads = []
Output: 2
Explanation: Close the only branch, or keep it open.
Constraints
1 <= n <= 101 <= maxDistance <= 10^50 <= roads.length <= 1000roads[i].length == 30 <= u, v <= n - 1u != v1 <= w <= 1000all branches are reachable from each other when every road is used
Hints for Number of Possible Sets of Closing Branches
Hint 1
With at most 10 branches there are at most
2^10 = 1024choices of which branches stay open — try them all.Hint 2
For one choice, you need shortest distances between open branches using only roads whose both ends are open. Floyd–Warshall over the open branches is short and fast enough.
Hint 3
Keep only the cheapest road between each pair, and count the choice when every pair of open branches ends up within
maxDistance(an empty or single-branch choice always counts).
How to solve Number of Possible Sets of Closing Branches
The number of branches is tiny, so enumerate every subset of open branches as a bitmask. For each subset, all-pairs shortest paths restricted to the open branches decide whether it is valid.
Approach
- Build
w[u][v], the cheapest road betweenuandv(infinity if none). - For each mask from 0 to
2^n − 1: copywrestricted to the open branches intod, withd[i][i] = 0. - Run Floyd–Warshall over the open branches only.
- If every pair of open branches has
d[i][j] <= maxDistance, count the mask.
Why it works
Closing a branch removes it and its roads, so the distances that matter are shortest paths in the subgraph induced by the open branches — exactly what the restricted Floyd–Warshall computes. Enumerating all masks covers every possible set of closed branches once.
Complexity
- Time —
O(2^n · n^3) - Space —
O(n^2)
Pitfalls
- Multiple roads can join the same pair; keep the shortest.
- Paths may not pass through closed branches — restrict the intermediate node in Floyd–Warshall too.
- Disconnected open branches have infinite distance and make the mask invalid; the empty mask and every single-branch mask are always valid.
Reference solution
Python
from typing import List
def numberOfSets(n: int, maxDistance: int, roads: List[List[int]]) -> int:
INF = float("inf")
w = [[INF] * n for _ in range(n)]
for u, v, c in roads:
if c < w[u][v]:
w[u][v] = w[v][u] = c
count = 0
for mask in range(1 << n):
nodes = [i for i in range(n) if mask >> i & 1]
d = [row[:] for row in w]
for i in nodes:
d[i][i] = 0
for k in nodes:
dk = d[k]
for i in nodes:
di = d[i]
dik = di[k]
if dik == INF:
continue
for j in nodes:
if dik + dk[j] < di[j]:
di[j] = dik + dk[j]
if all(d[i][j] <= maxDistance for i in nodes for j in nodes):
count += 1
return countJava
public static int numberOfSets(int n, int maxDistance, int[][] roads) {
final int INF = 1000000000;
int[][] w = new int[n][n];
for (int[] row : w) Arrays.fill(row, INF);
for (int[] r : roads) if (r[2] < w[r[0]][r[1]]) { w[r[0]][r[1]] = r[2]; w[r[1]][r[0]] = r[2]; }
int count = 0;
int[][] d = new int[n][n];
int[] nodes = new int[n];
for (int mask = 0; mask < (1 << n); mask++) {
int m = 0;
for (int b = 0; b < n; b++) if (((mask >> b) & 1) == 1) nodes[m++] = b;
for (int x = 0; x < n; x++) for (int y = 0; y < n; y++) d[x][y] = x == y ? 0 : w[x][y];
for (int p = 0; p < m; p++) {
int k = nodes[p];
for (int q = 0; q < m; q++) {
int s = nodes[q];
if (d[s][k] == INF) continue;
for (int t = 0; t < m; t++) {
int e = nodes[t];
if (d[s][k] + d[k][e] < d[s][e]) d[s][e] = d[s][k] + d[k][e];
}
}
}
boolean ok = true;
for (int f = 0; f < m && ok; f++)
for (int g = 0; g < m; g++)
if (d[nodes[f]][nodes[g]] > maxDistance) { ok = false; break; }
if (ok) count++;
}
return count;
}C++
int numberOfSets(int n, int maxDistance, vector<vector<int>>& roads) {
const int INF = 1000000000;
vector<vector<int>> w(n, vector<int>(n, INF)), d(n, vector<int>(n));
for (auto& r : roads) if (r[2] < w[r[0]][r[1]]) { w[r[0]][r[1]] = r[2]; w[r[1]][r[0]] = r[2]; }
int count = 0;
for (int mask = 0; mask < (1 << n); mask++) {
vector<int> nodes;
for (int b = 0; b < n; b++) if ((mask >> b) & 1) nodes.push_back(b);
for (int x = 0; x < n; x++) for (int y = 0; y < n; y++) d[x][y] = x == y ? 0 : w[x][y];
for (int k : nodes)
for (int s : nodes) {
if (d[s][k] == INF) continue;
for (int e : nodes)
if (d[s][k] + d[k][e] < d[s][e]) d[s][e] = d[s][k] + d[k][e];
}
bool ok = true;
for (int f : nodes) {
for (int g : nodes) if (d[f][g] > maxDistance) { ok = false; break; }
if (!ok) break;
}
if (ok) count++;
}
return count;
}JavaScript
var numberOfSets = function(n, maxDistance, roads) {
var INF = 1000000000;
var w = [];
for (var i = 0; i < n; i++) { w.push([]); for (var j = 0; j < n; j++) w[i].push(INF); }
for (var r = 0; r < roads.length; r++) {
var u = roads[r][0], v = roads[r][1], c = roads[r][2];
if (c < w[u][v]) { w[u][v] = c; w[v][u] = c; }
}
var count = 0;
var d = [];
for (var a = 0; a < n; a++) d.push(new Array(n));
for (var mask = 0; mask < (1 << n); mask++) {
var nodes = [];
for (var b = 0; b < n; b++) if ((mask >> b) & 1) nodes.push(b);
for (var x = 0; x < n; x++) for (var y = 0; y < n; y++) d[x][y] = x === y ? 0 : w[x][y];
for (var p = 0; p < nodes.length; p++) {
var k = nodes[p];
for (var q = 0; q < nodes.length; q++) {
var s = nodes[q];
if (d[s][k] === INF) continue;
for (var t = 0; t < nodes.length; t++) {
var e = nodes[t];
if (d[s][k] + d[k][e] < d[s][e]) d[s][e] = d[s][k] + d[k][e];
}
}
}
var ok = true;
for (var f = 0; f < nodes.length && ok; f++)
for (var g = 0; g < nodes.length; g++)
if (d[nodes[f]][nodes[g]] > maxDistance) { ok = false; break; }
if (ok) count++;
}
return count;
};Also on the editorial tab: C, C#, Go, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 146 bit manipulation problems · the whole catalogue
Learn the technique: Bit Manipulation · Graph Data Structure