📅  最后修改于: 2023-12-03 15:42:20.670000             🧑  作者: Mango
门|门CS 1996 | 第36题
给定 $n$ $(1<=n<=50)$ 个人,他们之间可能会存在矛盾,现在有若干辆车将这些人运走。要求运走的车数最少,同时保证每辆车中任意两个人之间都没有矛盾。
第一行:整数 $n$,表示人数。
接下来 $n$ 行,每行一个字符串 $s$,表示当前人和其他人是否存在矛盾的情况,其中 $s$ 的第 $i$ 个字符为 'Y'
表示当前人和第 $i$ 个人存在矛盾,为 'N'
表示不存在矛盾。
一行一个整数,表示运走的车数最少。
5
NYNNN
YNYNN
NYNYN
NNYNY
NNNYN
3
这道题可以使用贪心算法来解决。
我们可以将没有矛盾的人看做是一个个集合,而有矛盾的人看做是不同的集合,然后对集合进行合并,直到所有的人都在同一个集合中。
对于两个集合之间的合并,我们可以按照他们的大小进行合并,这样能够使得合并后的集合尽可能的小,从而运输的次数尽可能的少。
实现上,我们可以使用并查集来维护集合之间的关系,并记录每个集合的大小,然后按照大小进行合并即可。
设 $n$ 为人数,时间复杂度 $O(n^2 logn)$。
class UnionFind:
def __init__(self, n: int):
self.parent = [i for i in range(n)]
self.size = [1 for _ in range(n)]
self.count = n
def find(self, p: int) -> int:
while p != self.parent[p]:
self.parent[p] = self.parent[self.parent[p]]
p = self.parent[p]
return p
def union(self, p: int, q: int):
root_p, root_q = self.find(p), self.find(q)
if root_p == root_q:
return
if self.size[root_p] < self.size[root_q]:
self.parent[root_p] = root_q
self.size[root_q] += self.size[root_p]
else:
self.parent[root_q] = root_p
self.size[root_p] += self.size[root_q]
self.count -= 1
def get_count(self) -> int:
return self.count
def min_cars(n: int, conflicts: List[str]) -> int:
uf = UnionFind(n)
for i in range(n):
for j in range(i + 1, n):
if conflicts[i][j] == 'N':
uf.union(i, j)
return uf.get_count()
n = int(input())
conflicts = [input() for _ in range(n)]
print(min_cars(n, conflicts))