leetcode 6256. 将节点分成尽可能多的组 二分图判定+bfs+并查集

6256. 将节点分成尽可能多的组

难度困难

给你一个正整数 n ,表示一个 无向 图中的节点数目,节点编号从 1 到 n 。

同时给你一个二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示节点 ai 和 bi 之间有一条 双向 边。注意给定的图可能是不连通的。

请你将图划分为 m 个组(编号从 1 开始),满足以下要求:

  • 图中每个节点都只属于一个组。
  • 图中每条边连接的两个点 [ai, bi] ,如果 ai 属于编号为 x 的组,bi 属于编号为 y 的组,那么 |y - x| = 1 。

请你返回最多可以将节点分为多少个组(也就是最大的 m )。如果没办法在给定条件下分组,请你返回 -1 。

 

示例 1:

输入:n = 6, edges = [[1,2],[1,4],[1,5],[2,6],[2,3],[4,6]]
输出:4
解释:如上图所示,
- 节点 5 在第一个组。
- 节点 1 在第二个组。
- 节点 2 和节点 4 在第三个组。
- 节点 3 和节点 6 在第四个组。
所有边都满足题目要求。
如果我们创建第五个组,将第三个组或者第四个组中任何一个节点放到第五个组,至少有一条边连接的两个节点所属的组编号不符合题目要求。

示例 2:

输入:n = 3, edges = [[1,2],[2,3],[3,1]]
输出:-1
解释:如果我们将节点 1 放入第一个组,节点 2 放入第二个组,节点 3 放入第三个组,前两条边满足题目要求,但第三条边不满足题目要求。
没有任何符合题目要求的分组方式。

 

提示:

  • 1 <= n <= 500
  • 1 <= edges.length <= 104
  • edges[i].length == 2
  • 1 <= ai, bi <= n
  • ai != bi
  • 两个点之间至多只有一条边

 

解法一
class Solution: def magnificentSets(self, n: int, edges: List[List[int]]) -> int: adjList = [[] for _ in range(n)] uf = UnionFind(n) for u, v in edges: u, v = u - 1, v - 1 adjList[u].append(v) adjList[v].append(u) uf.union(u, v) if not isBipartite(n, adjList): return -1 return sum(calDiameter(n, adjList, group) + 1 for group in uf.getGroups().values()) def calDiameter(n: int, adjList: List[List[int]], group: List[int]) -> int: """bfs求连通分量 `group` 的直径长度""" res = 0 for start in group: visited, queue = set([start]), deque([start]) diameter = -1 while queue: len_ = len(queue) for _ in range(len_): cur = queue.popleft() for next in adjList[cur]: if next in visited: continue visited.add(next) queue.append(next) diameter += 1 res = max(res, diameter) return res def isBipartite(n: int, adjList: List[List[int]]) -> bool: """二分图检测 dfs染色""" def dfs(cur: int, color: int) -> bool: colors[cur] = color for next in adjList[cur]: if colors[next] == -1: if not dfs(next, color ^ 1): return False elif colors[next] == color: return False return True colors = [-1] * n for i in range(n): if colors[i] == -1 and not dfs(i, 0): return False return True class UnionFind: def __init__(self, n: int): self.n = n self.part = n self.parent = list(range(n)) self.rank = [1] * n def find(self, x: int) -> int: while x != self.parent[x]: self.parent[x] = self.parent[self.parent[x]] x = self.parent[x] return x def union(self, x: int, y: int) -> bool: rootX = self.find(x) rootY = self.find(y) if rootX == rootY: return False if self.rank[rootX] > self.rank[rootY]: rootX, rootY = rootY, rootX self.parent[rootX] = rootY self.rank[rootY] += self.rank[rootX] self.part -= 1 return True def getGroups(self) -> DefaultDict[int, List[int]]: groups = defaultdict(list) for key in range(self.n): root = self.find(key) groups[root].append(key) return groups

  

解法二
# class Solution:
#     def magnificentSets(self, n: int, edges: List[List[int]]) -> int:        
#         g = [[] for _ in range(n)]
#         for x, y in edges:
#             g[x - 1].append(y -1)
#             g[y - 1].append(x - 1)

#         time = [0] * n 
#         clock = 0 
#         def bfs(start):
#             depth = 0 
#             nonlocal clock 
#             clock += 1 
#             time[start] = clock
#             q = [start]
#             while q:
#                 tmp = q 
#                 q = []
#                 for x in tmp:
#                     for y in g[x]:
#                         if time[y] != clock:
#                             time[y] = clock
#                             q.append(y)
#                 depth += 1 
#             return depth

#         color = [0] * n 
#         def is_bipartite(x, c):
#             nodes.append(x)
#             color[x] = c 
#             for y in g[x]:
#                 if color[y] == c or color[y] == 0 and not is_bipartite(y, -c):
#                     return False
#             return True 

#         ans = 0 
#         for i, c in enumerate(color):
#             if c: continue 
#             nodes = [] 
#             print (color)
#             t = is_bipartite(i, 1)
#             print (color)
#             if not t: return -1 
#             ans += max(bfs(x) for x in nodes)
#             print (ans)
        
#         return ans

 

posted on 2022-12-04 23:11  爱装逼的书呆子  阅读(37)  评论(0编辑  收藏  举报

导航