Example: Connecting cities - rFronteddu/general_wiki GitHub Wiki
There are N cities numbered from 1 to N.
You are given connections, where each connections[i] = [city1, city2, cost] represents the cost to connect city1 and city2 together. (A connection is bidirectional: connecting city1 and city2 is the same as connecting city2 and city1.)
Return the minimum cost so that for every pair of cities, there exists a path of connections (possibly of length 1) that connects those two cities together. The cost is the sum of the connection costs used. If the task is impossible, return -1.
Solution
We can use Kruskal's Algorithm:
- Sort edges in non-decreasing order.
- Implement UnionFind structure to manage connected component (to determine whether adding an edge will form a cycle)
- Process edges, add an edge if it connects two previously unconnected components. If it can, add its cost to the total cost and union the two components.
- Check Connectivity, number of edges in the MST must be N-1 otherwise it is not fully connected.
public static int minimumCost(int N, int[][] connections) {
// we can use Kruskal to compute the MST
Arrays.sort(connections, (a,b) -> Integer.compare(a[2], b[2]));
UnionFind unionFind = new UnionFind(N);
int totalCost = 0;
int edgeUsed = 0;
// process each edge
for (int[] connection : connections) {
// the -1 is to convert in 0-based index
int city1 = connection[0] - 1;
int city2 = connection[1] - 1;
int cost = connection[2];
// check if city1 and 2 are in different components
if (unionFind.find(city1) != unionFind.find(city2)) {
// add edge to MST
unionFind.union(city1, city2);
totalCost += cost;
edgeUsed++;
}
}
// check if all cities are connected
if (edgeUsed == N - 1) {
return totalCost;
}
return -1;
}
static class UnionFind {
private int[] parent;
private int[] rank;
public UnionFind(int size) {
parent = new int[size];
rank = new int[size];
for (int i = 0; i < size; i++) {
// each node is its own parent
parent[i] = i;
// initial rank
rank[i] = 1;
}
}
public int find(int city) {
if (parent[city] != city) {
// path compression
parent[city] = find(parent[city]);
}
return parent[city];
}
public void union(int city1, int city2) {
int root1 = find(city1);
int root2 = find(city2);
if (root1 != root2) {
// union by rank
if (Rank[root1] > rank[root2]) {
parent[root2] = root1;
} else if (rank[root1] < rank[root2]) {
parent[root1] = root2;
} else {
parent[root2] = root1;
rank[root1]++;
}
}
}
}