LC 5970. 参加会议的最多员工数
https://leetcode-cn.com/problems/maximum-employees-to-be-invited-to-a-meeting/
最初看到这里还有点懵,老想着可以当做一个问题来解决,后来意识到大约是两个问题:
- 如果回路的长度超过2的话,那么就只能使用这个回路,比如 A->B->C->A 的话就是一个闭环,不能和其他结果链接起来。
- 如果回路的长度是2的话,好比A<->B这样,那么可以分别从A和B向外链接其他结果,比如
- F->E->D->C->A<->B
- H->G->J->I->B<->A
- 并且2得到的结果可以混合在一起比如(这点我开始没有想到)
- D->C->A<->B<-I<-J
- 6->5->1<->2<-3<-4
- 之间是不会有任何冲突的
其中第一个问题比较好解决,第二个问题稍微有点绕,但是细想一下的话其实可以按照拓扑排序进行动态规划。以上面为例
- F(1) -> E(2) -> D(3) -> C(4) -> A(5)
- H(1) -> G(2) -> J(3) -> I(4) -> B(5)
- 那么A最长链路是5,B也是5,所以总长度就是10.
class Solution:
def maximumInvitations(self, favorite: List[int]) -> int:
n = len(favorite)
#========== 求解最长回路 ==========
def check_cycle():
cycle = [0] * n
res = 0
for i in range(n):
path, step, buf = {}, 0, []
x = i
while x not in path:
if cycle[x]: break
buf.append(x)
path[x] = step
step += 1
x = favorite[x]
if cycle[x]:
d = cycle[x]
else:
d = step - path[x]
for x in buf:
cycle[x] = d
res = max(res, d)
return res
cycle_size = check_cycle()
# ========== 按照拓扑顺序动态规划 ==========
deg = [0] * n
dp = [1] * n
from collections import deque
Q = deque()
for i in range(n):
deg[favorite[i]] += 1
for i in range(n):
if deg[i] == 0:
Q.append(i)
while Q:
x = Q.popleft()
to = favorite[x]
dp[to] = max(dp[to], dp[x] + 1)
deg[to] -= 1
if deg[to] == 0:
Q.append(to)
# ========== 将多个长度为2的回路拼接起来 ==========
concat_size = 0
for i in range(n):
if favorite[favorite[i]] == i and i < favorite[i]:
concat_size += dp[i] + dp[favorite[i]]
ans = max(cycle_size, concat_size)
return ans