并查集-最低成本联通所有城市

305 阅读1分钟

1135. 最低成本联通所有城市

想象一下你是个城市基建规划者,地图上有 n 座城市,它们按以 1 到 n 的次序编号。

给你整数 n 和一个数组 conections,其中 connections[i] = [xi, yi, costi] 表示将城市 xi 和城市 yi 连接所要的costi连接是双向的)。

返回连接所有城市的最低成本,每对城市之间至少有一条路径。如果无法连接所有 n 个城市,返回 -1

该 最小成本 应该是所用全部连接成本的总和。

 

示例 1:

输入: n = 3, conections = [[1,2,5],[1,3,6],[2,3,1]]
输出: 6
解释: 选出任意 2 条边都可以连接所有城市,我们从中选取成本最小的 2 条。

示例 2:

输入: n = 4, conections = [[1,2,3],[3,4,4]]
输出: -1
解释: 即使连通所有的边,也无法连接所有城市。

 

提示:

  • 1 <= n <= 104
  • 1 <= connections.length <= 104
  • connections[i].length == 3
  • 1 <= xi, yi <= n
  • xi != yi
  • 0 <= costi <= 105
/**
 * @param {number} n
 * @param {number[][]} connections
 * @return {number}
 */
var minimumCost = function(n, connections) {
	const unionFind = new UnionFind(n);
	let result = 0;
	connections.sort((a, b) => b[2] - a[2]);
	while(connections.length) {
		const [x, y, cost] = connections.pop();
		if (unionFind.union(x - 1, y - 1)) {
			result += cost;
		}

		if (unionFind.count === 1) {
			return result;
		}
	}
	return -1;
};


class UnionFind {
	constructor(count) {
		this.count = count;
		this.parents = [];
		this.sizes = new Array(count).fill(1);
		this.init();
	}

	init() {
		for (let i = 0; i < this.count; i++) {
			this.parents[i] = i;
		}
	}

	find(node) {
		let curNode = node;
		while (this.parents[curNode] !== curNode) {
			this.parents[curNode] = this.parents[this.parents[curNode]];
			curNode = this.parents[curNode];
		}
		return curNode;
	}

	union(left, right) {
		const leftRoot = this.find(left);
		const rightRoot = this.find(right);
		if (leftRoot !== rightRoot) {
			if (this.sizes[leftRoot] < this.sizes[rightRoot]) {
				this.parents[leftRoot] = rightRoot;
				this.sizes[rightRoot] += this.sizes[leftRoot];
			} else {
				this.parents[rightRoot] = leftRoot;
				this.sizes[leftRoot] += this.sizes[rightRoot];
			}
			this.count--;
			return true;
		}
		return false;
	}
}