There are n
computers numbered from 0
to n-1
connected by ethernet cables connections
forming a network where connections[i] = [a, b]
represents a connection between computers a
and b
. Any computer can reach any other computer directly or indirectly through the network.
Given an initial computer network connections
. You can extract certain cables between two directly connected computers, and place them between any pair of disconnected computers to make them directly connected. Return the minimum number of times you need to do this in order to make all the computers connected. If it's not possible, return -1.
Example 1:
Input: n = 4, connections = [[0,1],[0,2],[1,2]] Output: 1 Explanation: Remove cable between computer 1 and 2 and place between computers 1 and 3.
Example 2:
Input: n = 6, connections = [[0,1],[0,2],[0,3],[1,2],[1,3]] Output: 2
Example 3:
Input: n = 6, connections = [[0,1],[0,2],[0,3],[1,2]] Output: -1 Explanation: There are not enough cables.
Example 4:
Input: n = 5, connections = [[0,1],[0,2],[3,4],[2,3]] Output: 0
Constraints:
1 <= n <= 10^5
1 <= connections.length <= min(n*(n-1)/2, 10^5)
connections[i].length == 2
0 <= connections[i][0], connections[i][1] < n
connections[i][0] != connections[i][1]
- There are no repeated connections.
- No two computers are connected by more than one cable.
题目又多处出现关键词connected,可以确定是连通性问题,马上想到并查集(Union Find)。这道题的问法跟之前的并查集题稍有不同,但是万变不离其宗,仍然可以套用并查集(Union Find)模板。
题目说一个网络里可能有多个电脑组,不同电脑组之间没有连接关系,同一电脑组里的电脑之间通过网线直接或者间接的连接在一起,同一电脑组有些多余的网线可以被移除。如果两台电脑已经间接连在一起了,那么他们之间的直连网线就是多余网线可以被移除。移除的多余网线可以用来连接两个不相连的电脑组使得他们连在一起。现在问最少要移除多少条网线可以使得网络内所有不相连的电脑组最终都连在一起形成一个大的电脑组。
解题思路:
1)如何确定哪些网线是多余的?在用并查集合并两台直连的电脑时,如果这两台电脑已经在同一集合里,那这两台电脑的直连线就是多余网线。因此只要一遇到这种情况多余网线数就加1,最终就可以得到多余网线的总数。
2)如何确定最少需要几根网线可以把所有不相连的电脑组连在一起?在并查集合并完之后,如果最终有m个集合(即m个电脑组),那么最少就需要m-1根网线。
3)如果多余网线数小于m-1,那无论如何也不能把所有电脑组连在一起。
class UnionFind:
def __init__(self, n):
self.parent = list(range(0, n))
self.size = [1] * n
self.cnt = n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def merge(self, x, y):
px, py = self.find(x), self.find(y)
if px == py :
return False
if self.size[px] > self.size[py]:
self.parent[py] = px
self.size[px] += self.size[py]
else:
self.parent[px] = py
self.size[py] += self.size[px]
self.cnt -= 1
return True
class Solution:
def makeConnected(self, n: int, connections: List[List[int]]) -> int:
uf = UnionFind(n)
extra = 0
for c in connections:
if not uf.merge(c[0], c[1]):
extra += 1
return uf.cnt - 1 if extra >= uf.cnt - 1 else -1