leetcode:20210102周赛第四题——参加会议的最多员工数(基环树+找树枝+dfs最长树枝)
Posted 白速龙王的回眸
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode:20210102周赛第四题——参加会议的最多员工数(基环树+找树枝+dfs最长树枝)相关的知识,希望对你有一定的参考价值。
看看浙大学长(排名前20)的答案,好好学习
附上一个链接表示respect!
力扣原题答案
我的理解:
每个联通分量有且仅有一环
环中若只有2node,则需要反向找出最长的树枝(两边都找)
环中若大于2node,由于树枝节点不可进环,树枝节点不可成环,所以最多的人数就是环中人数
代码思路:
代码:
class Solution:
def maximumInvitations(self, g: List[int]) -> int:
# favorite就是内向基环森林g
n = len(g)
rg = [[] for _ in range(n)] # g的反图
deg = [0] * n # g上每个点的入度
for v, w in enumerate(g):
# 反图就是w指向v
rg[w].append(v)
deg[w] += 1
#print(deg)
#print(rg)
# 拓扑排序,剪掉g上的树枝
# deque是双向队列, 找出入度为0的
q = deque(i for i, d in enumerate(deg) if d == 0)
#print(q)
# 递归找树枝
while q:
# v是树枝末梢
v = q.popleft()
# 树枝的上一个
w = g[v]
# 剪掉树枝v
deg[w] -= 1
# 判断剪掉v后w是否变成了树枝末梢
# 这时候deg为0的都变成了树枝
if deg[w] == 0:
# 右边加
q.append(w)
# 通过反图rg寻找树枝上最深的链
def rdfs(v: int) -> int:
max_depth = 1
# v的反图中
for w in rg[v]:
# 若入度为0,则是树枝节点
if deg[w] == 0:
max_depth = max(max_depth, rdfs(w) + 1)
return max_depth
# 找出环元素>2的最大环元素个数
# 找出换元素=2的最长树枝深度(包括基环那两个)
max_ring_size, sum_chain_size =0, 0
for i, d in enumerate(deg):
# 不管树枝
if d <= 0:
continue
# 遍历基环上的点
deg[i] = -1
ring_size = 1
v = g[i]
while v != i:
deg[v] = -1 #将基环上的点的入度标记为-1,避免重复访问
ring_size += 1
v = g[v]
# 若基环大小为2
if ring_size == 2:
# 累计两条最长链的长度
sum_chain_size += rdfs(i) + rdfs(g[i])
else:
# 取所有基环的最大值
max_ring_size = max(max_ring_size, ring_size)
return max(max_ring_size, sum_chain_size)
基环为2之所以可以累加的解释
总结:
1.这种谁喜欢谁模型可是内向基环图森林
2.基环大于2,则不可插入,且树枝不可组合,所以此时最大人数为基环(基环构成一个圈)
3.基环等于2,要计算两边各自最长链的和,且所有基环等于2的可以拼接起来
4.用rg、deg和enumerate记录反图(找最长链)和度数
5.用双向队列deque+拓扑排序(满足边的先后关系)找到所有树枝
6.dfs找反向的最长链
7.遍历deg,找出环中的点,分>2和==2两种情况
8.两者取max
以上是关于leetcode:20210102周赛第四题——参加会议的最多员工数(基环树+找树枝+dfs最长树枝)的主要内容,如果未能解决你的问题,请参考以下文章