LeetCode 1319. 連通網路的操作次數(中等)
阿新 • • 發佈:2021-02-01
1319. 連通網路的操作次數
用乙太網線纜將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]
- 沒有重複的連線。
- 兩臺計算機不會通過多條線纜連線。
我的Java程式碼:
思路:這個問題實際上就是一個無向連通圖的問題。要把 n 個結點連起來,至少需要 n-1 條邊,如果邊數小於 n-1 那就無法完成操作,返回 -1 。而對於邊數足夠的情況下,要用最少的操作,即移動最少的邊,就要看圖中有幾個連通子圖,如果只有m個連通子圖,那麼用 m-1 條邊即可把這 m 個子圖連成一整個連通圖。這裡考慮用並查集來儲存圖中結點和其連通關係,並得到圖中連通子圖的個數。
class Solution {
public int makeConnected(int n, int[][] connections) {
if(connections.length < n-1) {
return -1;
}
int len = connections.length;
UnionFind unionfind = new UnionFind(n);
for(int i = 0;i < len;i++) {
int x = connections[i][0];
int y = connections[i][1];
if(!unionfind.isConnected(x, y)) {
unionfind.union(x, y);
}
}
int num = unionfind.getNum(n);
return num-1;
}
private class UnionFind{
private int[] fathers;
private int[] ranks;
public UnionFind(int n) {
fathers = new int[n];
ranks = new int[n];
for(int i = 0;i < n;i++) {
fathers[i] = i;
ranks[i] = 1;
}
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if(rootX == rootY) {
return;
}
if(ranks[rootX] > ranks[rootY]) {
fathers[rootY] = rootX;
}else {
fathers[rootX] = rootY;
}
if(ranks[rootX] == ranks[rootY]){
ranks[rootY]++;
}
}
public int find(int x) {
if(x != fathers[x]) {
fathers[x] = find(fathers[x]);
}
return fathers[x];
}
public boolean isConnected(int x, int y) {
int rootX = find(x);
int rootY = find(y);
return (rootX==rootY);
}
public int getNum(int n) {
int num = 0;
for(int i = 0;i < n;i++) {
if(i == find(i)) {
num++;
}
}
return num;
}
}
}