1135 Connecting Cities With Minimum Cost
There are n cities labeled from 1 to n. You are given the integer n and an array connections where connections[i] = [xi, yi, costi] indicates that the cost of connecting city xi and city yi (bidirectional connection) is costi.
Return the minimum cost to connect all the n cities such that there is at least one path between each pair of cities. If it is impossible to connect all the n cities, return -1,
The cost is the sum of the connections' costs used.
class Prim {
constructor(graph) {
this.graph = graph;
this.weightSum = 0;
// 优先队列,按照边的权重从小到大排序
this.pq = new MinPriorityQueue();
// 图中有 n 个节点
const n = graph.length;
// 布尔数组 inMST 辅助,防止重复计算横切边
this.inMST = new Array(n).fill(false);
// 从任意一点开始切分,我们从节点 0 开始
this.inMST[0] = true;
this.cut(0);
// 不断进行切分,向最小生成树中添加边
while (!this.pq.isEmpty()) {
const edge = this.pq.dequeue();
const to = edge.element[1];
const weight = edge.element[2];
if (this.inMST[to]) {
continue;
}
// 将边 edge 加入最小生成树
this.weightSum += weight;
this.inMST[to] = true;
// 新加入的节点 to 进行切分,产生更多横切边
this.cut(to);
}
}
/**
* 将 s 的横切边加入优先队列
* @param {number} s - 节点编号
*/
cut(s) {
// 遍历 s 的所有邻边
for (const edge of this.graph[s]) {
const to = edge[1];
if (this.inMST[to]) continue;
// 将边加入优先队列
this.pq.enqueue(edge, edge[2]);
}
}
/**
* 获取最小生成树的权重和
* @returns {number}
*/
getWeightSum() {
return this.weightSum;
}
/**
* 判断最小生成树是否包含图中的所有节点
* @returns {boolean}
*/
allConnected() {
return this.inMST.every(inTree => inTree);
}
}
/**
* @param {number} n
* @param {number[][]} connections
* @return {number}
*/
var minimumCost = function(n, connections) {
function buildGraph(n, connections) {
const graph = Array.from({ length: n }, () => []);
for (const [u, v, weight] of connections) {
graph[u - 1].push([u - 1, v - 1, weight]);
graph[v - 1].push([v - 1, u - 1, weight]);
}
return graph;
}
const graph = buildGraph(n, connections);
const prim = new Prim(graph);
if (!prim.allConnected()) {
return -1;
}
return prim.getWeightSum();
};