2127. 参加会议的最多员工数 : 啥是内向/外向基环树(拓扑排序)
题目描述
这是 LeetCode 上的 「2127. 参加会议的最多员工数」 ,难度为 「困难」。
Tag : 「拓扑排序」、「内向基环树」、「图」
一个公司准备组织一场会议,邀请名单上有 n 位员工。
公司准备了一张圆形的桌子,可以坐下任意数目的员工。
员工编号为 到 。每位员工都有一位喜欢的员工,每位员工当且仅当他被安排在喜欢员工的旁边,他才会参加会议,每位员工喜欢的员工不会是他自己。
给你一个下标从 开始的整数数组 favorite,其中 表示第 位员工喜欢的员工。请你返回参加会议的最多员工数目。
示例 1: 
输入:favorite = [2,2,1,2]
输出:3
解释:
上图展示了公司邀请员工 0,1 和 2 参加会议以及他们在圆桌上的座位。
没办法邀请所有员工参与会议,因为员工 2 没办法同时坐在 0,1 和 3 员工的旁边。
注意,公司也可以邀请员工 1,2 和 3 参加会议。
所以最多参加会议的员工数目为 3 。
示例 2:
输入:favorite = [1,2,0]
输出:3
解释:
每个员工都至少是另一个员工喜欢的员工。所以公司邀请他们所有人参加会议的前提是所有人都参加了会议。
座位安排同图 1 所示:
- 员工 0 坐在员工 2 和 1 之间。
- 员工 1 坐在员工 0 和 2 之间。
- 员工 2 坐在员工 1 和 0 之间。
参与会议的最多员工数目为 3 。
示例 3: 
输入:favorite = [3,0,1,4,1]
输出:4
解释:
上图展示了公司可以邀请员工 0,1,3 和 4 参加会议以及他们在圆桌上的座位。
员工 2 无法参加,因为他喜欢的员工 0 旁边的座位已经被占领了。
所以公司只能不邀请员工 2 。
参加会议的最多员工数目为 4 。
提示:
内向基环树 + 拓扑排序
根据题意,圆形桌上 左右两边只要有一位是 所喜欢即可。
我们可从 向 添加有向边,从而得到一张包含多个「内向基环树」的图。
内向基环树,是指其满足基环树定义,且内向 bushi。
基环树是指其具有 个点 条边的联通块,而「内向」是指树中任意节点有且只有一条出边,对应的「外向」是指树中任意节点有且只有一条入边。
例如,左图内向,右图外向:
根据题意,「圆桌最多放置一个长度大于 的环(内向环,只有一条出边,即只有一个喜欢的人,安插其他非环成员,会破坏留下参加会议的必要条件),但可放置多个长度为 的环,且多个环可延伸出最长链(利用左右两侧只需有一个喜欢的人即满足)。」
在「取长度大于 的最大环」及「多个长度为 的环及其最长链之和」两者中取最大长度即是答案。
Java 代码:
class Solution {
public int maximumInvitations(int[] favorite) {
int n = favorite.length;
// in 统计每个节点的入度情况, max 统计节最长链
int[] in = new int[n], max = new int[n];
for (int x : favorite) in[x]++;
Deque<Integer> d = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
if (in[i] == 0) d.addLast(i);
}
// 拓扑排序: 求基环外的最长链
while (!d.isEmpty()) {
int cur = d.pollFirst(), ne = favorite[cur];
max[ne] = Math.max(max[ne], max[cur] + 1);
if (--in[ne] == 0) d.addLast(ne);
}
// 圆桌最多放置一个大于 2 的环(ans1 统计最大值)
// 圆桌可放置多个等于 2 的环(ans2 累加该长度)
int ans1 = 0, ans2 = 0;
for (int i = 0; i < n; i++) {
if (in[i] == 0) continue;
int j = favorite[i], cur = 1;
while (j != i) {
// 一个环只需被处理一次, 这里将环中其他节点入度置 0, 下次遍历到这些点就会被跳过
in[j] = 0;
j = favorite[j];
cur++;
}
if (cur == 2) ans2 += 2 + max[i] + max[favorite[i]];
else ans1 = Math.max(ans1, cur);
}
return Math.max(ans1, ans2);
}
}
Python 代码:
class Solution:
def maximumInvitations(self, favorite: List[int]) -> int:
n = len(favorite)
# in_degree 统计每个节点的入度情况, max_length 统计节最长链
in_degree, max_length = [0] * n, [0] * n
for x in favorite:
in_degree[x] += 1
d = deque()
for i in range(n):
if in_degree[i] == 0:
d.append(i)
# 拓扑排序: 求基环外的最长链
while d:
cur = d.popleft()
ne = favorite[cur]
max_length[ne] = max(max_length[ne], max_length[cur] + 1)
in_degree[ne] -= 1
if in_degree[ne] == 0:
d.append(ne)
# 圆桌最多放置一个大于 2 的环(ans1 统计最大值)
# 圆桌可放置多个等于 2 的环(ans2 累加该长度)
ans1, ans2 = 0, 0
for i in range(n):
if in_degree[i] == 0:
continue
j, cur = favorite[i], 1
while j != i:
# 一个环只需被处理一次, 这里将环中其他节点入度置 0, 下次遍历到这些点就会被跳过
in_degree[j] = 0
j = favorite[j]
cur += 1
if cur == 2:
ans2 += 2 + max_length[i] + max_length[favorite[i]]
else:
ans1 = max(ans1, cur)
return max(ans1, ans2)
C++ 代码:
class Solution {
public:
int maximumInvitations(vector<int>& favorite) {
int n = favorite.size();
// in 统计每个节点的入度情况, max_length 统计节最长链
vector<int> in(n, 0);
vector<int> max_length(n, 0);
for (int x : favorite) in[x]++;
deque<int> d;
for (int i = 0; i < n; i++) {
if (in[i] == 0) d.push_back(i);
}
// 拓扑排序: 求基环外的最长链
while (!d.empty()) {
int cur = d.front();
d.pop_front();
int ne = favorite[cur];
max_length[ne] = max(max_length[ne], max_length[cur] + 1);
if (--in[ne] == 0) d.push_back(ne);
}
// 圆桌最多放置一个大于 2 的环(ans1 统计最大值)
// 圆桌可放置多个等于 2 的环(ans2 累加该长度)
int ans1 = 0, ans2 = 0;
for (int i = 0; i < n; i++) {
if (in[i] == 0) continue;
int j = favorite[i], cur = 1;
while (j != i) {
// 一个环只需被处理一次, 这里将环中其他节点入度置 0, 下次遍历到这些点就会被跳过
in[j] = 0;
j = favorite[j];
cur++;
}
if (cur == 2) ans2 += 2 + max_length[i] + max_length[favorite[i]];
else ans1 = max(ans1, cur);
}
return max(ans1, ans2);
}
};
TypeScript 代码:
function maximumInvitations(favorite: number[]): number {
const n = favorite.length;
// in_degree 统计每个节点的入度情况, max_length 统计节最长链
const in_degree = Array(n).fill(0), max_length = Array(n).fill(0);
for (const x of favorite) in_degree[x]++;
const d = [];
for (let i = 0; i < n; i++) {
if (in_degree[i] === 0) d.push(i);
}
// 拓扑排序: 求基环外的最长链
while (d.length > 0) {
const cur = d.shift() as number;
const ne = favorite[cur];
max_length[ne] = Math.max(max_length[ne], max_length[cur] + 1);
if (--in_degree[ne] === 0) d.push(ne);
}
// 圆桌最多放置一个大于 2 的环(ans1 统计最大值)
// 圆桌可放置多个等于 2 的环(ans2 累加该长度)
let ans1 = 0, ans2 = 0;
for (let i = 0; i < n; i++) {
if (in_degree[i] === 0) continue;
let j = favorite[i], cur = 1;
while (j !== i) {
// 一个环只需被处理一次, 这里将环中其他节点入度置 0, 下次遍历到这些点就会被跳过
in_degree[j] = 0;
j = favorite[j];
cur++;
}
if (cur == 2) ans2 += 2 + max_length[i] + max_length[favorite[i]];
else ans1 = Math.max(ans1, cur);
}
return Math.max(ans1, ans2);
};
-
时间复杂度:统计入度的复杂度为 ;拓扑排序求最长链复杂度为 ;计算答案过程中,每个点最多被访问两次(环内节点),复杂度为 。整体复杂度为 -
空间复杂度:
最后
这是我们「刷穿 LeetCode」系列文章的第 No.2217 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉
相关文章:
2127. 参加会议的最多员工数 : 啥是内向/外向基环树(拓扑排序)
题目描述 这是 LeetCode 上的 「2127. 参加会议的最多员工数」 ,难度为 「困难」。 Tag : 「拓扑排序」、「内向基环树」、「图」 一个公司准备组织一场会议,邀请名单上有 n 位员工。 公司准备了一张圆形的桌子,可以坐下任意数目的员工。 员工…...
Qt入门日记1
目录 1.Qt简介和案例 2.第一个Qt程序 3.学会查看帮助文档 4.创建一个按钮 5.对象树简介 6.Qt的坐标系 7. 信号和槽 7.1自定义信号和槽 7.2信号连接信号 7.3拓展 7.4Qt4版本以前的connect 1.Qt简介和案例 Qt是一个跨平台的C图形用户界面应用程序框架(就是一个库吧…...
SpringBoot_第七章(读写分离)
这里列举了三种读写分离实现方案,分别是如下三种 1:MybatisPlus(读写分离) 1.1:首先创建三个数据库1主2从 表名是user表 1.2:代码实例 1:导入pom <!--MybatisPlus的jar 3.0基于jdk8--><depend…...
linux下mysql-8.2.0集群部署(python版本要在2.7以上)
目录 一、三台主机准备工作 1、mysql官方下载地址:https://dev.mysql.com/downloads/ 2、修改/etc/hosts 3、关闭防火墙 二、三台主机安装mysql-8.2.0 1、解压 2、下载相应配置 3、初始化mysql,启动myslq,设置开机自启 4、查看初始密…...
40 深度学习(四):卷积神经网络|深度可分离卷积|colab和kaggle的基础使用
文章目录 卷积神经网络为什么要卷积卷积的具体流程池化tensorflow代码 深度可分离卷积原理介绍计算量对比代码参数计算例子 colab 和 kagglecolabkaggle如何在colab上使用kaggle的数据 卷积神经网络 卷积神经网络的基本结构 1: (卷积层(可选)池化层) * N全连接层 *…...
Spring Boot面向切面加注解
一.项目pom.xml文件引入切面依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>二.定义注解类 import java.lang.annotation.*;/*** desc 错误日志注解* au…...
uniapp小程序授权统一处理
1.使用 1.将工具代码引入到utils中 const authorize (scope, isOne false, isMust false) > {if (!scope || !authorizeObj[scope]) {return console.error(请传输需要获取权限的 scope,详见,https://uniapp.dcloud.net.cn/api/other/authorize.html#scope-…...
光学仿真|优化汽车内部照明体验
当我们谈论优化人类感知的内部照明时,我们实际上指的是两个重点领域:安全性和驾驶员体验。如果内部照明可以提供尽可能最佳的体验,驾驶员则能够更好地应对颇具挑战性或意外的驾驶状况,并且减轻疲劳感。除了功能优势外,…...
Spring XML使用CASE WHEN处理SELECT字段
在日常开发中,经常会碰到需要导出的情况。而一些枚举值或者状态一般是定义成整型,这个时候需要对数据进行转换,转换成对应的文本再导出。 在XML中用CASE WHEN来根据不同的查询结果做不同的处理。 比如 SELECT name AS 姓名, age AS 年龄 C…...
关于C#中使用多线程的讨论
关于C#中使用多线程的讨论 C# 中 Thread 调用的函数有返回值 没有输入应该如何解决 如果你想在一个新的线程中调用一个带返回值但没有输入参数的函数,可以使用 Thread 类的委托 ThreadStart 来创建一个新的线程,并在其中调用该函数。然后,你可以使用 Thread 类的 Join 方法…...
工程机械数字孪生可视化平台建设,推动大型装备智能化数字化转型升级
随着信息技术的迅猛发展,数字孪生技术作为一项新兴技术应运而生。数字孪生是指通过数学模型和仿真技术,将实际物理对象与其数字化虚拟模型相互关联,实现对物理对象的全生命周期管理和智能优化。在工程机械领域,巨蟹数科从数字孪生…...
Linux 网络流量监控利器 iftop命令详解及实战
简介 iftop 是什么 在 Linux 系统下即时监控服务器的网络带宽使用情况,有很多工具,比如 iptraf、nethogs 等等,但是推荐使用小巧但功能很强大的 iftop 工具。 iftop 是 Linux 系统一个免费的网卡实时流量监控工具,类似于 top 命令…...
protected by SourceGuardian and requires a SourceGuardian loader ‘ixed.8解决方案
php相关问题 安装程序提示以下内容 遇到某些php程序的安装提示: PHP script ‘/www/wwwroot/zhengban.youyacao.com/install/index.php’ is protected by SourceGuardian and requires a SourceGuardian loader ‘ixed.8.1.lin’ to be installed. 1) Click her…...
KWin、libdrm、DRM从上到下全过程 —— drmModeAddFBxxx(14)
接前一篇文章:KWin、libdrm、DRM从上到下全过程 —— drmModeAddFBxxx(13) 上一回讲完了drivers/gpu/drm/drm_framebuffer.c中的framebuffer_check函数中的第一个for循环,本回继续讲解framebuffer_check()接下来的代码。为了便于理解,再次贴出其源码,如下所示: static …...
2023-macOS下安装anaconda,终端自动会出现(base)字样,如何取消
2023-macOS下安装anaconda,终端自动会出现(base)字样,如何取消 安装后,我们再打开终端,就会自动出现了(base) 就会出现这样子的,让人头大, 所以我们要解决它 具体原因是 安装了anac…...
Nginx搭载负载均衡及前端项目部署
目录 编辑 一.Nginx安装 1.安装所需依赖 2.下载并解压Nginx安装包 3.安装nginx 4.启动Nginx服务 二.Tomcat负载均衡 1.准备环境 1.1 准备两个Tomcat 1.2 修改端口号 1.3 配置Nginx服务器集群 2.效果展示 编辑三.前端项目打包 编辑四.前端项目部署 1.上传项目…...
深度学习——炼丹
学习率调整策略 自定义学习率调整策略 简单版 net MyNet()optimoptim.Adam(net.parameters(),lr0.05) for param_group in optim.param_groups: param_group["lr"] param_group["lr"]*0.5print(param_group["lr"]) #0.25复杂版&#…...
Matlab中的app设计
1.窗口焦点问题: 窗口焦点问题:确保你的应用程序窗口正常处于焦点状态。有时,其他窗口的弹出或焦点切换可能导致应用程序最小化。点击应用程序窗口以确保它处于焦点状态。 窗口管理:确保你的 MATLAB 或操作系统没有未处理的错误或…...
曾经遇到过的无法解释的问题
因为不能直接展示生产数据与生产数据结构,所以写一个简单的例子 class Stu{ private String name; private int age; getter setter constructor 略 } List<Stu> list new ArrayList(); list.add(new Stu("s1",16)); list.add(new Stu("…...
基于uniapp与uview做一个按拼音首字母排序的通讯录页面
效果图: 第一步导入pinyin库并应用,用于区分汉字的拼音首字母 npm i pinyin import pinyin from "pinyin" 完整算法: function getListByPinyinFirstLetter(data) {const newList {};for (const item of data) {let firstLett…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...
从零开始了解数据采集(二十八)——制造业数字孪生
近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...
UE5 音效系统
一.音效管理 音乐一般都是WAV,创建一个背景音乐类SoudClass,一个音效类SoundClass。所有的音乐都分为这两个类。再创建一个总音乐类,将上述两个作为它的子类。 接着我们创建一个音乐混合类SoundMix,将上述三个类翻入其中,通过它管理每个音乐…...
MeshGPT 笔记
[2311.15475] MeshGPT: Generating Triangle Meshes with Decoder-Only Transformers https://library.scholarcy.com/try 真正意义上的AI生成三维模型MESHGPT来袭!_哔哩哔哩_bilibili GitHub - lucidrains/meshgpt-pytorch: Implementation of MeshGPT, SOTA Me…...
