2076.处理含限制条件的好友请求
https://leetcode-cn.com/problems/process-restricted-friend-requests/
一、并查集
class UnionFind:
# 构造函数传入totalNodes为总节点数
def __init__(self, totalNodes):
# parents[i]表示i的根,初始i的根为其自身
self.parents = [i for i in range(totalNodes)]
# 连通分量数
self.count = totalNodes
# 连通分量大小,即树的“重量”
self.size = [1] * totalNodes
# 合并连通区域是通过find来操作的, 即看这两个节点是不是在一个连通区域内.
def union(self, node1, node2):
root1 = self.find(node1)
root2 = self.find(node2)
# 不连通才合并
if root1 != root2:
# 小树合并到大树
if self.size[root1] > self.size[root2]:
self.parents[root2] = root1
self.size[root1] += self.size[root2]
else:
self.parents[root1] = root2
self.size[root2] += self.size[root1]
# 连通分量数减一
self.count -= 1
# 查找最终的根
def find(self, node):
while self.parents[node] != node:
self.parents[node] = self.parents[self.parents[node]]
node = self.parents[node]
return node
# 判断两个点是否连通
def isConnected(self, node1, node2):
return self.find(node1) == self.find(node2)
# 返回连通分量个数
def count(self):
return self.count
算法:每轮将前i个(i从0到n-1)好友请求(设为[a,b])写入并查集,即把a,b连通。然后用限制集中的每个限制关系c、d进行测试,若c与d连通,说明这i个请求不能成立(确切的说是第i个)
class Solution:
def friendRequests(self, n: int, restrictions: List[List[int]], requests: List[List[int]]) -> List[bool]:
res = []
passIndex = set() #标记不能成立的请求
for i in range(len(requests)):
uf = UnionFind(n) #每轮创建一个并查集
for j in range(i+1):
if j in passIndex: #若该请求被标记不能成立,则跳过
continue
a, b = requests[j][0], requests[j][1]
uf.union(a,b)
flag = True
for c, d in restrictions: #测试所有限制条件
if uf.isConnected(c, d):
flag = False
passIndex.add(i)
break
res.append(flag)
return res
优化
每个集合内都是直接朋友或者间接朋友。
对于:x = requests[i][0], y = requests[i]
如果x所处的集合与y所处的集合相等,这样就意味着x和y已经是朋友了 如果x所处的集合与y所处的集合不等,需要判断x所处的集合与y所处的集合能否合并,可以遍历restrictions,具体如下:
对于:p = restrictions[j][0], q = restrictions[j][1]
有以下两种情况不合符条件 如果x与p在同一个集合 且 q与y在同一个集合 如果y与p在同一个集合 且 x与q在同一个集合 上面两种情况都说明,若x与y成为朋友,则p和q成为间接朋友,这是限制条件不允许的
# 并查集模板略
class Solution:
def friendRequests(self, n: int, restrictions: List[List[int]], requests: List[List[int]]) -> List[bool]:
res = []
uf = UnionFind(n)
for x, y in requests:
flag = True
if not uf.isConnected(x, y):
for p, q in restrictions:
if uf.isConnected(p, x) and uf.isConnected(q, y) or uf.isConnected(q, x) and uf.isConnected(p, y):
flag = False
break
if flag:
uf.union(x, y)
res.append(flag)
return res
最后更新于