【每日一题Day365】LC2172参加会议的最多员工数 | 拓扑排序

简介: 【每日一题Day365】LC2172参加会议的最多员工数 | 拓扑排序

参加会议的最多员工数【LC2127】

一个公司准备组织一场会议,邀请名单上有 n 位员工。公司准备了一张 圆形 的桌子,可以坐下 任意数目 的员工。

员工编号为 0 到 n - 1 。每位员工都有一位 喜欢 的员工,每位员工 当且仅当 他被安排在喜欢员工的旁边,他才会参加会议。每位员工喜欢的员工 不会 是他自己。

给你一个下标从 0 开始的整数数组 favorite ,其中 favorite[i] 表示第 i 位员工喜欢的员工。请你返回参加会议的 最多员工数目 。

思路:拓扑排序

  • 内向基环树概念:从i向favorite[i]连边,可以得到一张有向图。由于每个大小为k的连通块都有k个点和k边,所以每个连通块必定有且仅有一个环,且由于每个点的出度均为 1,这样的有向图又叫做内向基环树
  • 本题中有两种基环树

长度为2时,圆桌上可以放置多个长度等于2的环,及其最长链

长度大于2时,圆桌上只能放置一个长度大于2的环

因为相邻员工都需要有一位喜欢的员工

长度等于2的环内两位员工互相喜欢,在其边上可以再增加最长链【贪心,获得最多员工】,最长链的末尾又可以添加其他长度为2的环【结果1】

长度大于2的环内无法再添加其他员工【结果2】

最终答案为结果1和结果2的最大值

实现

可以使用拓扑排序找到基环和数值,并记录每个节点的最长链,计算两种内向基环树对应的结果

通过一次拓扑排序,可以「剪掉」所有树枝。因为拓扑排序后,树枝节点的入度均为 0,基环节点的入度均为 1。这样就可以将基环和树枝区分开,从而简化后续处理流程:

如果要遍历基环,可以从入度为 1的节点出发,遍历其余入度为 1 的节点。

如果要遍历树枝,可以以基环与树枝的连接处为起点,顺着反图来遍历树枝,从而将问题转化成一个树形问题。

作者:灵茶山艾府

链接:https://leetcode.cn/problems/maximum-employees-to-be-invited-to-a-meeting/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
    public int maximumInvitations(int[] favorite) {
        int n = favorite.length;
        int[] deg = new int[n];
        for (int f : favorite) {
            deg[f]++; // 统计基环树每个节点的入度
        }
        int[] maxDepth = new int[n];
        Deque<Integer> q = new ArrayDeque<>();
        for (int i = 0; i < n; i++) {
            if (deg[i] == 0) {
                q.add(i);
            }
        }
        while (!q.isEmpty()) { // 拓扑排序,剪掉图上所有树枝
            int x = q.poll();
            int y = favorite[x]; // x 只有一条出边
            maxDepth[y] = maxDepth[x] + 1;
            if (--deg[y] == 0) {
                q.add(y);
            }
        }
        int maxRingSize = 0, sumChainSize = 0;
        for (int i = 0; i < n; i++) {
            if (deg[i] == 0) continue;
            // 遍历基环上的点
            deg[i] = 0; // 将基环上的点的入度标记为 0,避免重复访问
            int ringSize = 1; // 基环长度
            for (int x = favorite[i]; x != i; x = favorite[x]) {
                deg[x] = 0; // 将基环上的点的入度标记为 0,避免重复访问
                ringSize++;
            }
            if (ringSize == 2) { // 基环长度为 2
                sumChainSize += maxDepth[i] + maxDepth[favorite[i]] + 2; // 累加两条最长链的长度
            } else {
                maxRingSize = Math.max(maxRingSize, ringSize); // 取所有基环长度的最大值
            }
        }
        return Math.max(maxRingSize, sumChainSize);
    }
}
作者:灵茶山艾府
链接:https://leetcode.cn/problems/maximum-employees-to-be-invited-to-a-meeting/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

复杂度

时间复杂度:O ( n )

空间复杂度:O ( n )

目录
相关文章
|
10月前
|
算法 测试技术 C#
C++二分算法:最多可以参加的会议数目 II
C++二分算法:最多可以参加的会议数目 II
|
10月前
|
算法 测试技术 C#
【图论】【基环内向树】【广度优先】【深度优先】2127. 参加会议的最多员工数
【图论】【基环内向树】【广度优先】【深度优先】2127. 参加会议的最多员工数
|
10月前
|
算法 测试技术 C#
C++动态规划算法:最多可以参加的会议数目
C++动态规划算法:最多可以参加的会议数目
|
10月前
蓝桥备战--纪念品分组OJ532,贪心证明
蓝桥备战--纪念品分组OJ532,贪心证明
38 0
ACM刷题之路(九)数论-逆序组 交换座位
ACM刷题之路(九)数论-逆序组 交换座位
【每日一题Day73】LC2037使每位学生都有座位的最少移动次数 | 排序+贪心
思路:要使总移动次数最少,那么要将每个学生移动至离其最近的座位,因此将座位和学生的位置进行升序排序,每个学生需要的移动次数即为对应位置相减,累加返回最终结果
119 0
|
存储 人工智能
PAT-2021年秋季考试 乙级 7-4 数组与链表 (20 分)
让我们来设计这样一种数组与链表结合的整数存储的结构 A
151 0
L1-049 天梯赛座位分配 (20 分)
L1-049 天梯赛座位分配 (20 分)
326 0
L1-078 吉老师的回归 (15 分)
L1-078 吉老师的回归 (15 分)
328 0
7-35 部落 (10 分)
7-35 部落 (10 分)
83 0