【每日一题】参加会议的最多员工数

news2025/2/27 21:07:25

文章目录

  • Tag
  • 题目来源
  • 题目解读
  • 解题思路
    • 方法一:内向基环树+拓扑排序+分类讨论
      • 内向基环树
      • 分类讨论
        • 基环长度大于 2
        • 基环长度等于 2
      • 功能实现
  • 写在最后

Tag

【内向基环树+拓扑排序+分类讨论】【图】【2023-11-01】


题目来源

2127. 参加会议的最多员工数


题目解读

员工只有坐在自己喜欢的员工旁边才会参加会议,请问参加会议的最多员工数。


解题思路

方法一:内向基环树+拓扑排序+分类讨论

内向基环树

k 个点和 k 条边的有向图必定有且仅有一个环,这样的有向图叫做内向基环树。 内向基环树中的环被称为基环,一个单独的环也可以被称为基环。内向基环树通常由一个基环和其余指向基环的树枝组成。一棵典型的内向基环树如下图所示:

图中的蓝色节点表示基环上的节点,绿色节点表示树枝上的节点。

题目中给定的员工之间的座位要求(每个员工必须坐在喜欢的员工旁边),如果我们把员工看成是图上的一个节点,如果员工 x 喜欢员工 y,就在从 x 对应的节点到 y 对应的节点之间连一条边,那么形成的就是由若干颗内向基环树组成的图。按照上述员工之间的连接规则,示例 3 构成的图为:

分类讨论

明确了员工之间的内向基环树关系之后,接下来需要对基环长度进行讨论(因为不同的基环长度对结果会产生明显的区别),有以下两种情况:

  • 基环长度大于 2
  • 基环长度等于 2
  • 没有其他情况了,基环的长度最小为 2
基环长度大于 2

先来看一下基环长度大于 2 的情况,该情况下树枝是无法插入到基环中两个节点之间的。因为,树枝上的点若插入圆桌上 x→y 这两人中间,会导致节点 x 无法和其喜欢的员工坐在一起。此外,树枝上的点也不能单独组成圆桌,因为这样会存在一个出度为 0 的节点,无法和其喜欢的员工坐在一起。

因此,对于基环长度大于 2 的情况,圆桌的最大员工数目即为最大的基环长度,记作 maxRingSize

基环长度等于 2

基环树的长度为 2 时,比如下面这种情况:

我们可以先让员工 21 坐在圆桌旁,员工 2 在左侧,员工 1 在右侧,那么 2 这一侧的树枝只能坐在 2 的左侧,而 1 这一侧的树枝只能坐在 1 的右侧。0 可以紧靠着 2 的左侧坐下,45 只能有一个人坐在 0 的左侧。为了在圆桌旁坐下尽可能多的人,我们需要从 2 出发,沿着反图方向的边找,每个点在其反图上只能选择一个子节点,最后找到一条最长的链,即图中加粗的节点。

对于 1 一侧同理。将这两条最长链的长度之和即为该基环树能组成的圆桌的最大员工数。

对于多个基环长度等于 2 的基环树,每个基环树所对应的链,都可以拼在其余链的末尾,因此可以将这些链全部拼成一个圆桌,其大小记作 sumChainSize

最终返回的答案即为 max⁡(maxRingSize,sumChainSize)

功能实现

解题思路已经理清楚了,现在要来看看需要实现哪些功能(做什么):

  • 建立反图;
  • 根据反图求图中树枝上的最大链;
  • 求图中所有基环的长度,按照基环的长度来分类讨论参加会议的最多员工数量。

建立反图

先统计所有节点的入度,然后从入度为 0 的节点开始,建立反图。

求最大链
根据反图求图中树枝上的最大链,就是求二叉树的最大深度的题目,使用递归实现,代码为:

int maxDepth(int x) {
    int maxDepth = 1;
    for (int son : rg[x]) {
        maxDepth = max(maxDepth, maxDepth(son) + 1);
    }
    return maxDepth;
}

基环的长度

我们枚举所有的节点,因为我们已经在拓扑排序的时候将树枝节点的入度全部置为 0 了,所以在枚举中遇到入度为 1 的节点,那么该节点一定是基环的入环点。

实现代码

class Solution {
public:
    int maximumInvitations(vector<int>& favorite) {
        int n = favorite.size();
        vector<int> deg(n);
        // 统计基环树每个节点的入度
        for (int f : favorite) {
            ++deg[f];
        }

        queue<int> que;
        for (int i = 0; i < n; ++i) {
            if (deg[i] == 0) {
                que.push(i);
            }
        }

        // 拓扑排序建反图
        vector<vector<int>> rg(n);
        while (!que.empty()) {
            int x = que.front();
            que.pop();
            int y = favorite[x];
            rg[y].push_back(x);
            if (--deg[y] == 0) {
                que.push(y);
            }
        }

        // 根据反图求图中树枝上的最大链
        function<int(int)> rdfs = [&](int x) -> int {
            int maxDepth = 1;
            for (int son : rg[x]) {
                maxDepth = max(maxDepth, rdfs(son) + 1);
            }
            return maxDepth;
        };

        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) {
                sumChainSize += rdfs(i) + rdfs(favorite[i]);// 累加两条最长链的长度
            }
            else {
                maxRingSize = max(maxRingSize, ringSize);   // 取所有基环长度的最大值
            }
        }
        return max(maxRingSize, sumChainSize);
    }
};

复杂度分析

时间复杂度: O ( n ) \mathcal{O(n)} O(n)。其中 n n nfavorite 的长度。拓扑排序和遍历基环均为 O ( n ) \mathcal{O(n)} O(n)

空间复杂度: O ( n ) \mathcal{O(n)} O(n)


写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1158320.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿昌教你如何优雅的数据脱敏

阿昌教你如何优雅的数据脱敏 Hi&#xff0c;我是阿昌&#xff0c;最近有一个数据脱敏的需求&#xff0c;要求用户可自定义配置数据权限&#xff0c;并对某种类型数据进行脱敏返回给前端 一、涉及知识点 SpringMVCJava反射Java自定义注解Java枚举 二、方案选择 1、需求要求…

呼叫中心的重要考核指标

呼叫中心在运营过程中越来越精细化&#xff0c;在信息化管理的时代&#xff0c;呼叫中心系统是必不可少的&#xff0c;而呼叫中心的管理人员为了提升运营效率&#xff0c;通常会根据业务目标设置各种业务的考核指标&#xff0c;而我也根据OKCC在呼叫中心项目运营过程中的经验&a…

【双十一预售】玩得越来越大了...

双十一又又又到了 剁手带来的快乐终究是短暂的 让自己变得更优秀才是长远的快乐 当今大环境 工作难找&#xff0c;钱难赚 只有不断学习与成长 方能应对未来的各种不确定性 知了堂双十一预售 0.11元畅享三大权益 助你快速实现自我提升 突破成长瓶颈 https://appyqk1x…

1. 网络之网络通信基础

网络通信基础 文章目录 网络通信基础1. IP地址2. 端口号3. 协议3.1 三要素3.2 作用 4. 五元组5. 协议分层5.1 OSI七层模型5.2 TCP/IP 五层模型5.2.1 应用层5.2.2 传输层5.2.3 网络层5.2.3 数据链路层5.2.5 物理层 6. 封装和分用6.1 发送方 - 封装6.2 中间转发6.3 接收方 - 分用…

codeMirror代码编辑器,如何定位并在编辑区域输入内容

背景 最近在写UI自动化&#xff0c;发现普通的方法不能在CodeMirror编辑器里面输入内容&#xff0c;只能通过JS的方式输入内容。 于是琢磨了一下selenium和playwright这2种自动化工具&#xff0c;在CodeMirror编辑器里面输入内容的差别。 注意&#xff1a;这里在定位CodeMirr…

轧钢厂安全生产方案:AI视频识别安全风险智能监管平台的设计

一、背景与需求 轧钢厂一般都使用打包机对线材进行打包作业&#xff0c;由于生产需要&#xff0c;人员需频繁进入打包机内作业&#xff0c;如&#xff1a;加护垫、整包、打包机检修、调试等作业。在轧钢厂生产过程中&#xff0c;每个班次生产线材超过300件&#xff0c;人员在一…

【OpenCV实现图像找到轮廓的不同特征,就像面积,周长,质心,边界框等等。】

文章目录 概要图像矩凸包边界矩形 概要 OpenCV是一个流行的计算机视觉库&#xff0c;它提供了许多图像处理和分析功能&#xff0c;其中包括查找图像中物体的轮廓。通过查找轮廓&#xff0c;可以提取许多有用的特征&#xff0c;如面积、周长、质心、边界框等。 以下是几种使用…

双目视觉检测 KX02-SY1000型测宽仪 有效修正和消除距离变化对测量的影响

双目视觉检测的基本原理 利用相机测量宽度时&#xff0c;由于单个相机在成像时存在“近大远小”的现象&#xff0c;并且单靠摄入的图像无法知道被测物的距离&#xff0c;所以由被测物的跳动导致的被测物到工业相机之间距离变化&#xff0c;使测量精度难以提高。 因此测宽仪需…

Vue项目创建与启动(2023超详细的图文教程)

目录 一、下载node.js 二、下载vue-cli与webpack插件 三、项目初始化(项目配置详细信息) 四、项目启动 五、Vue项目工程结构&#xff08;扩展知识&#xff09; 一、下载node.js 1.检测是否已经安装过node.js 打开控制台,输入 npm -v如果有会显示对应版本 如果没有会显示…

RocketMQ消费者和队列对应关系

参考 RocketMQ 5.0 POP 消费模式探秘 https://www.cnblogs.com/alisystemsoftware/p/15535925.html 旧版本MQ结论 消费者应用和topic队列一对多的关系。 &#xff08;一个消费组consumer group里&#xff0c;一个消费者应用可以消费多个队列的消息。一个队列的消息只能被一个…

矩阵分块例子

有如下矩阵A和B 对A列分块, B行分块后结果如下 对A行分块, B列分块后结果如下

企业网络带宽使用情况检查技巧

想要提高网络性能的企业通常会考虑限制对占用带宽的应用程序&#xff08;如社交媒体和视频流应用程序&#xff09;的访问&#xff0c;但对于那些真正需要获得高效网络的人来说&#xff0c;这还不够&#xff0c;您需要定期跟踪带宽使用情况。 虽然有许多工具可以帮助您检查网络…

Webpack的代码分割(code splitting)

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

干洗店服务预约小程序有什么作用

要说干洗店&#xff0c;近些年的需求度非常高&#xff0c;一方面是人们生活品质提升&#xff0c;另一方面则是各种服饰对洗涤要求提升等&#xff0c;很多人的衣服很多也会通过干洗店进行清洁。 而对从业商家来说&#xff0c;市场庞大一方面需要不断进行市场教育、品牌提升&…

Python自动化测试实战篇:unittest框架详解

为什么要学习unittest 按照测试阶段来划分&#xff0c;可以将测试分为单元测试、集成测试、系统测试和验收测试。单元测试是指对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作&#xff0c;通常指函数或者类&#xff0c;一般是开发完成的。 单元…

CMake:构建时为特定目标运行自定义命令

CMake&#xff1a;构建时为特定目标运行自定义命令 导言项目结构相关源码结果 导言 add_custom_command 是 CMake 中用于添加自定义构建规则的命令&#xff0c;通常用于在编译项目时执行一些自定义操作&#xff0c;例如生成文件、运行脚本等。 项目结构 . ├── CMakeLists…

《web前端开发技术》初识Vue + 第一个 Vue程序:hello world

目录 2.1 Vue 简述 2.1.1 什么是 Vue 2.1.2 为什么选择 Vue 2.2 Vue 的三种安装方式 2.1 Vue 简述 Vue 在 JavaScript 前端开发库领域属于后来者&#xff0c;其他前端开发库有 jQuery、ExtJS、 Anguals、React 等。 2.1.1 什么是 Vue &#x1f636;‍&#x1f32b;️Vue (…

树结构及其算法-二叉树遍历

目录 树结构及其算法-二叉树遍历 一、中序遍历 二、后序遍历 三、前序遍历 C代码 树结构及其算法-二叉树遍历 我们知道线性数组或链表都只能单向从头至尾遍历或反向遍历。所谓二叉树的遍历&#xff08;Binary Tree Traversal&#xff09;&#xff0c;简单的说法就是访问树…

Aqua Data Studio 2023.1

为什么选择 Aqua Data Studio&#xff1f; 随着数据在业务中的作用不断发展&#xff0c;组织需要一种有效的方法来简化复杂的技术任务并缩小 IT 和业务团队之间的差距。 使用多个数据库平台不再复杂。使用 Aqua Data Studio 简化您的所有数据管理流程和任务&#xff1a;这是一…

[JavaWeb]——获取请求参数的方式(全面!!!)

&#x1f308;键盘敲烂&#xff0c;年薪30万&#x1f308; 目录 1.普通类型 1.1原始方式(了解) 1.2springboot方式(推荐) 2.实体类型 2.1简单实体类型 2.2实体类型里还有实体类型(内部类) 3.数组或集合类型 3.1数组 3.2集合 4.&#x1f525;JSON格式 常用 5.日期类型…