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最长树枝)的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode周赛第194场周赛

LeetCode周赛第 291 场周赛(Go语言实现版)

LeetCode周赛第195场周赛

LeetCode周赛第 288 场周赛(Go语言实现版)

LeetCode周赛第 288 场周赛(Go语言实现版)

LeetCode周赛第 288 场周赛(Go语言实现版)