题目描述:
用以太网线缆将 n 台计算机连接成一个网络,计算机的编号从 0 到 n-1。线缆用 connections 表示,其中 connections[i] = [a, b] 连接了计算机 a 和 b。
网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。
给你这个计算机网络的初始布线 connections,你可以拔开任意两台直连计算机之间的线缆,并用它连接一对未直连的计算机。请你计算并返回使所有计算机都连通所需的最少操作次数。如果不可能,则返回 -1 。
示例 1:
输入:n = 4, connections = [[0,1],[0,2],[1,2]]
输出:1
解释:拔下计算机 1 和 2 之间的线缆,并将它插到计算机 1 和 3 上。
示例 2:
输入:n = 6, connections = [[0,1],[0,2],[0,3],[1,2],[1,3]]
输出:2
示例 3:
输入:n = 6, connections = [[0,1],[0,2],[0,3],[1,2]]
输出:-1
解释:线缆数量不足。
示例 4:
输入:n = 5, connections = [[0,1],[0,2],[3,4],[2,3]]
输出:0
提示:
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]
没有重复的连接。
两台计算机不会通过多条线缆连接。
方法1:
主要思路:解题汇总链接
(1)并查集;
(2)若是想连接 n 个点,则至少需要 n-1 条边,如若给出的连接条件小于 n-1 ,则可以直接返回-1,一定不能连接所有的点;
(3)否则,就确定出现在的 n 个点,在使用了给出的连接边之后,可以分为多少组,则再将所有的组连接到一起的最少操作次数就是组的数量减去1;
(4)确定组的数量,可以使用并查集;
class Solution {
public:
//并查集
int find_father(vector<int>&father,int index){
int ori_index=index;
while(father[index]!=index){//确定当前要查的结点所属的组
index=father[index];
}
while(father[ori_index]!=ori_index){//压缩连接的路径
int tmp=father[ori_index];
father[ori_index]=index;
ori_index=tmp;
}
return index;
}
int makeConnected(int n, vector<vector<int>>& connections) {
if(connections.size()<n-1){//说明一定不能连接成一组
return -1;
}
vector<int> father(n,0);//并查集初始化
for(int i=0;i<n;++i){
father[i]=i;
}
for(auto&con:connections){//逐个的加入连接的边
//确定当前两个点的所属的组
int f1=find_father(father,con[0]);
int f2=find_father(father,con[1]);
if(f1!=f2){//说明两个点此时还不属于一个组
father[f1]=f2;//将两个组连接
}
}
//确定有多少个组
int res=0;
for(int i=0;i<n;++i){
if(father[i]==i){
++res;
}
}
return res-1;
}
};