Open azl397985856 opened 1 year ago
class UF:
def __init__(self, n):
self.f = list(range(n))
self.size = [1] * n
self.count = n
def find(self, x):
if self.f[x] != x:
self.f[x] = self.find(self.f[x])
return self.f[x]
def union(self, x, y):
fx, fy = self.find(x), self.find(y)
if fx == fy: return
if self.size[fx] < self.size[fy]:
fx, fy = fy, fx
self.size[fx] += self.size[fy]
self.f[fy] = fx
self.count -= 1
class Solution:
def makeConnected(self, n: int, connections: List[List[int]]) -> int:
# n 个电脑
#
if len(connections) < n - 1:
return -1
uf = UF(n)
for x, y in connections:
uf.union(x, y)
# print(n)
# print(uf.count)
# print(len(connections))
return uf.count - 1
# 总共有3条边, 2个连通块 -> 3 - 2 = 1
# 总共有5条边, 3个连通块, 5 - 3 = 2
# n个点, 至少需要有n-1条边
class Solution {
vector<int> fa;
vector<int> rank;
public:
int findx(int x) {
return x == fa[x] ? x : fa[x] = findx(fa[x]);
}
bool unionmerge(int i, int j) {
int fx = findx(i), fy = findx(j);
if (fx == fy)
return true;
if (rank[fx] < rank[fy])
swap(fx, fy);
fa[fy] = fx;
rank[fx] += rank[fy];
return true;
}
int makeConnected(int n, vector<vector<int>>& connections) {
int cns = connections.size();
if (n - 1 > cns)
return -1;
sort(connections.begin(), connections.end());
int island = 0;
fa.resize(n);
rank.resize(n, 1);
for (int i = 0; i < n; i++)
{
fa[i] = i;
}
for (int i = 0; i < cns; i++)
{
unionmerge(connections[i][0], connections[i][1]);
}
for (int i = 0; i < n; i++)
{
if (fa[i] == i)
++island;
}
return island - 1;
}
};
class Solution: def makeConnected(self, n: int, connections: List[List[int]]) -> int: if len(connections)<n-1: return -1 visited = [] dic = {i:[] for i in range(n)} for con in connections: dic[con[0]].append(con[1]) dic[con[1]].append(con[0]) count = 0 for i in range(n): if i not in visited: count +=1 sets = [i] visited.append(i) while sets: k = sets.pop() if dic[k]: for j in dic[k]: if j not in visited: sets.append(j) visited.append(j) return count -1
thought
做完之后发现官方题解的方法直接返回 连通分量-1,没有多余的判断。
非常好奇为什么可以这样做,他的数学推导应该不成立才对。
然后就看到了两条题目限制条件,原来推导是建立在这上面的啊。
code
private int[] parent;
private int[] rank;
private int count;
public int makeConnected(int n, int[][] connections) {
parent = new int[n];
rank = new int[n];
count = n;
for (int i = 0; i < n; i++) {
parent[i] = i;
rank[i] = 1;
}
int cables = 0;
for (int[] connection : connections) {
if (!union(connection[0], connection[1]))
cables++;
}
count--;
return cables < count ? -1 : count;
}
private int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}
private boolean union(int p, int q) {
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) return false;
if (rank[pRoot] >= rank[qRoot])
parent[qRoot] = parent[pRoot];
else
parent[pRoot] = parent[qRoot];
if (rank[pRoot] == rank[qRoot])
rank[pRoot]++;
count--;
return true;
}
class Solution: def makeConnected(self, n: int, connections: List[List[int]]) -> int: par = {i: i for i in range(n)} rank = {i: 1 for i in range(n)}
def find(n1):
while n1 != par[n1]:
par[n1] = par[par[n1]]
n1 = par[n1]
return n1
def union(n1, n2):
p1, p2 = find(n1), find(n2)
if p1 == p2:
return 0
if rank[p1] < rank[p2]:
p1, p2 = p2, p1
par[p2] = p1
rank[p1] += rank[p2]
return 1
# redundant connections
redun = sum(1 for i, j in connections if not union(i, j))
# number of connected components
comp = sum(1 for i in range(n) if find(i) == i)
return comp - 1 if redun >= comp - 1 else -1
class Solution: def makeConnected(self, n: int, connections: List[List[int]]) -> int: root = [i for i in range(n)]
def find(p):
while p != root[p]:
root[p] = root[root[p]]
p = root[p]
return p
def union(p, q):
root[find(p)] = find(q)
have = 0
for connec in connections:
a, b = connec
if find(a) != find(b):
union(a, b)
else:
have += 1
diff_root = set()
for i in range(n):
diff_root.add(find(i))
return len(diff_root) - 1 if have >= len(diff_root) - 1 else -1
/**
DSU TC: O(M*α(N)) SC: O(N)
*/
class Solution {
public int makeConnected(int N, int[][] connections) {
int M = connections.length;
if (M < N - 1) return -1;
DSU dsu = new DSU(N);
int count = N - 1;
for (int[] c : connections) {
if (dsu.union(c[0], c[1]))
count--;
}
return count;
}
class DSU {
int[] parent;
int[] rank;
public DSU(int N) {
parent = new int[N];
rank = new int[N];
Arrays.setAll(parent, r->r);
}
public int find(int x) {
if (parent[x] != x)
parent[x] = find(parent[x]);
return parent[x];
}
public boolean union(int a, int b) {
int pa = find(a);
int pb = find(b);
if (pa == pb) return false;
if (rank[pa] < rank[pb]) {
parent[pa] = pb;
} else if (rank[pa] > rank[pb]) {
parent[pb] = pa;
} else {
parent[pb] = pa;
rank[pa]++;
}
return true;
}
}
}
class Solution:
def makeConnected(self, n: int, connections: List[List[int]]) -> int:
if len(connections) < n - 1:
return -1
edges = collections.defaultdict(list)
for x, y in connections:
edges[x].append(y)
edges[y].append(x)
seen = set()
def dfs(u: int):
seen.add(u)
for v in edges[u]:
if v not in seen:
dfs(v)
ans = 0
for i in range(n):
if i not in seen:
dfs(i)
ans += 1
return ans - 1
class Solution {
vector<int> fa;
vector<int> rank;
public:
int findx(int x) {
return x == fa[x] ? x : fa[x] = findx(fa[x]);
}
bool unionmerge(int i, int j) {
int fx = findx(i), fy = findx(j);
if (fx == fy)
return true;
if (rank[fx] < rank[fy])
swap(fx, fy);
fa[fy] = fx;
rank[fx] += rank[fy];
return true;
}
int makeConnected(int n, vector<vector<int>>& connections) {
int cns = connections.size();
if (n - 1 > cns)
return -1;
sort(connections.begin(), connections.end());
int island = 0;
fa.resize(n);
rank.resize(n, 1);
for (int i = 0; i < n; i++)
{
fa[i] = i;
}
for (int i = 0; i < cns; i++)
{
unionmerge(connections[i][0], connections[i][1]);
}
for (int i = 0; i < n; i++)
{
if (fa[i] == i)
++island;
}
return island - 1;
}
};
class Solution {
private:
vector<vector<int>> edges;
vector<int> used;
public:
void dfs(int u) {
used[u] = true;
for (int v: edges[u]) {
if (!used[v]) {
dfs(v);
}
}
}
int makeConnected(int n, vector<vector<int>>& connections) {
if (connections.size() < n - 1) {
return -1;
}
edges.resize(n);
for (const auto& conn: connections) {
edges[conn[0]].push_back(conn[1]);
edges[conn[1]].push_back(conn[0]);
}
used.resize(n);
int ans = 0;
for (int i = 0; i < n; ++i) {
if (!used[i]) {
dfs(i);
++ans;
}
}
return ans - 1;
}
};
/**
* @param {number} n
* @param {number[][]} connections
* @return {number}
*/
class UnionFind {
constructor(n) {
this.parents = [];
for (let i = 0; i < n; i++) {
this.parents[i] = i;
}
}
find(x) {
if (x === this.parents[x]) return x;
const root = this.find(this.parents[x]);
this.parents[x] = root;
return root;
}
union(x, y) {
const x_ = this.find(x);
const y_ = this.find(y);
if (x_ === y_) return 0;
this.parents[x_] = y_;
return 1;
}
}
/**
* @param {number} n
* @param {number[][]} connections
* @return {number}
*/
var makeConnected = function (n, connections) {
if(connections.length < n - 1) return -1
const u = new UnionFind(n)
for(const [x, y] of connections) u.union(x, y)
let ans = -1
for(let i = 0; i < n; i++){
if(u.parents[i] === i) ans++
}
return ans
};
class Solution {
private int[] p;
private int find(int x){
if(p[x] != x){
return find(p[x]);
}
return p[x];
}
public int makeConnected(int n, int[][] connections) {
if(connections.length < n - 1){
return -1;
}
p = new int[n];
for(int i = 0; i < n; i++){
p[i] = i;
}
int res = n;
for(int[] connection : connections){
int a = connection[0];
int b = connection[1];
if(find(a) != find(b)){
p[find(a)] = find(b);
res--;
}
}
return res - 1;
}
}
class Solution {
public int makeConnected(int n, int[][] connections) {
if (n - 1 > connections.length) {
return -1;
}
UnionFind unionFind = new UnionFind(n);
for (int[] connection : connections) {
unionFind.union(connection[0], connection[1]);
}
return unionFind.cnt - 1;
}
class UnionFind {
public int cnt;
public int[] parents;
public UnionFind(int n) {
this.cnt = n;
this.parents = new int[n];
for (int i = 0; i < n; i++) {
parents[i] = i;
}
}
public void union(int x, int y) {
int x_root = find(x);
int y_root = find(y);
if (x_root != y_root) {
cnt--;
}
parents[x_root] = y_root;
}
public int find(int x) {
if (x == parents[x]) {
return x;
}
parents[x] = find(parents[x]);
return parents[x];
}
}
}
class UnionFind:
def __init__(self, n: int):
self.parent = list(range(n))
self.size = [1] * n
self.n = n
# 当前连通分量数目
self.setCount = n
def findset(self, x: int) :
if self.parent[x] == x:
return x
self.parent[x] = self.findset(self.parent[x])
return self.parent[x]
def union(self, x: int, y: int):
x, y = self.findset(x), self.findset(y)
if x == y:
return False
if self.size[x] < self.size[y]:
x, y = y, x
self.parent[y] = x
self.size[x] += self.size[y]
self.setCount -= 1
return True
class Solution:
def makeConnected(self, n: int, connections: List[List[int]]) -> int:
uf = UnionFind(n)
if len(connections)<n-1:
return -1
for x, y in connections:
uf.union(x, y)
return uf.setCount - 1
class UnionFind: def init(self, n: int): self.parent = list(range(n)) self.size = [1] * n self.n = n
self.setCount = n
def findset(self, x: int) :
if self.parent[x] == x:
return x
self.parent[x] = self.findset(self.parent[x])
return self.parent[x]
def union(self, x: int, y: int):
x, y = self.findset(x), self.findset(y)
if x == y:
return False
if self.size[x] < self.size[y]:
x, y = y, x
self.parent[y] = x
self.size[x] += self.size[y]
self.setCount -= 1
return True
class Solution: def makeConnected(self, n: int, connections: List[List[int]]) -> int:
uf = UnionFind(n)
if len(connections)<n-1:
return -1
for x, y in connections:
uf.union(x, y)
return uf.setCount - 1
```
var makeConnected = function(n, connections) {
if (connections.length < n - 1) {
return -1;
}
const edges = new Map();
for (const [x, y] of connections) {
edges.get(x) ? edges.get(x).push(y) : edges.set(x, [y]);
edges.get(y) ? edges.get(y).push(x) : edges.set(y, [x]);
}
const used = new Array(n).fill(0);
let ans = 0;
for (let i = 0; i < n; i++) {
if (!used[i]) {
dfs(i, used, edges);
ans++;
}
}
return ans - 1;
};
const dfs = (u, used, edges) => {
used[u] = 1;
if (edges.get(u)) {
for (const v of edges.get(u)) {
if (!used[v]) {
dfs(v, used, edges);
}
}
}
}
class Solution {
public:
int makeConnected(int n, vector<vector<int>>& connections) {
if (connections.size() < n - 1) {
return -1;
}
vector<int> fa(n);
iota(fa.begin(), fa.end(), 0); //从0开始自增初始化
function<int(int)> findset = [&](int x) {return x == fa[x] ? x : fa[x] = findset(fa[x]);};
//通过std::function对C++中各种可调用实体(普通函数、Lambda表达式、函数指针、仿函数以及其它函数对象等)的封装,形成一个新的可调用的、统一的std::function对象。
int part = n;
for (auto&& c: connections) {
int p = findset(c[0]), q = findset(c[1]);
if (p != q) {
--part;
fa[p] = q;
}
}
return part - 1;
}
};
class Solution: def makeConnected(self, n: int, connections: List[List[int]]) -> int: if len(connections) < n - 1: return -1
edges = collections.defaultdict(list)
for x, y in connections:
edges[x].append(y)
edges[y].append(x)
seen = set()
def dfs(u: int):
seen.add(u)
for v in edges[u]:
if v not in seen:
dfs(v)
ans = 0
for i in range(n):
if i not in seen:
dfs(i)
ans += 1
return ans - 1
const int N = 1e5 + 10;
class Solution {
public:
int count, a[N];
void init(int n) {
count = n;
for (int i = 0; i < n; i++) a[i] = i;
}
int find(int x) {
if (a[x] != x) a[x] = a[find(a[x])];
return a[x];
}
bool unio(int i, int j) {
int x = find(i), y = find(j);
if (x == y) return false;
a[x] = y;
count--;
return true;
}
int makeConnected(int n, vector<vector<int>>& connections) {
init(n);
int cable = 0;
for (vector<int> temp : connections) {
int i = temp[0], j = temp[1];
if (!unio(i, j)) cable++;
}
count--; // 需要用于连接的线为总个数 - 1
return cable < count ? -1 : count;
}
};
线最少需要n-1根,找出不连通的有几堆,减去1就是需要补充的线的根数,即移动根数
/**
* @param {number} n
* @param {number[][]} connections
* @return {number}
*/
var makeConnected = function(n, connections) {
// 线不够
if (connections.length < n-1) {
return -1;
}
const parent = Array.from({ length: n }, (v, i) => i);
function find(v) {
if (parent[v] !== v) {
parent[v] = find(parent[v]);
}
return parent[v];
}
function union(x, y) {
const xset = find(x);
const yset = find( y);
if (xset != yset) {
parent[xset] = yset;// x指向y
res--;
}
}
var res = n;
for (const connection of connections) {
union(...connection);
}
// 块-1为需要的补充的线,即移动的线
return res -1;
};
时间:O(logx)并查集查找的次数 空间:O(n)并查集需要使用的空间
class Solution {
private:
vector<vector<int>> edges;
vector<int> used;
public:
void dfs(int u) {
used[u] = true;
for (int v: edges[u]) {
if (!used[v]) {
dfs(v);
}
}
}
int makeConnected(int n, vector<vector<int>>& connections) {
if (connections.size() < n - 1) {
return -1;
}
edges.resize(n);
for (const auto& conn: connections) {
edges[conn[0]].push_back(conn[1]);
edges[conn[1]].push_back(conn[0]);
}
used.resize(n);
int ans = 0;
for (int i = 0; i < n; ++i) {
if (!used[i]) {
dfs(i);
++ans;
}
}
return ans - 1;
}
};
1319. 连通网络的操作次数
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/number-of-operations-to-make-network-connected/
前置知识
暂无
题目描述