Skip to content

Commit 66b25b9

Browse files
authored
feat: add solutions to lc problem: No.2127 (doocs#1910)
No.2127.Maximum Employees to Be Invited to a Meeting
1 parent 0646ca2 commit 66b25b9

File tree

5 files changed

+179
-48
lines changed

5 files changed

+179
-48
lines changed

solution/2100-2199/2127.Maximum Employees to Be Invited to a Meeting/README.md

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,19 @@
7070

7171
**方法一:图的最大环 + 最长链**
7272

73-
问题等价于求有向图的最大环,以及所有长度为 $2$ 的环加上其最长链。求这两者的较大值
73+
我们观察发现,题目中员工的喜好关系可以看作一个有向图,这个有向图可以分成多个“基环内向树”的结构。在每个结构中,包含一个环,而环上的每个节点都连接着一棵树
7474

75-
求最长链到长度为 $2$ 的环,可以用拓扑排序
75+
什么是“基环内向树”?首先,基环树是一个具有 $n$ 个节点 $n$ 条边的有向图,而内向树是指这个有向图中,每个节点都有且仅有一条出边。本题中,每个员工都有且仅有一个喜欢的员工,因此,构成的有向图可以由多个“基环内向树”构成
7676

77-
时间复杂度 $O(n)$。
77+
<img alt="" src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/2100-2199/2127.Maximum%20Employees%20to%20Be%20Invited%20to%20a%20Meeting/images/05Dxh9.png"></p>
78+
79+
对于本题,我们可以求出图的最大环的长度,这里我们只需要求出最大的一个环的长度,这是因为,如果有多个环,那么不同环之间是不连通的,不符合题意。
80+
81+
另外,对于环的大小等于 $2$ 的长度,即存在两个员工互相喜欢,那么我们可以把这两个员工安排在一起,如果这两个员工各自被别的员工喜欢,那么我们只需要把喜欢他们的员工安排在他们的旁边即可。如果有多个这样的情况,我们可以把他们都安排上。
82+
83+
因此,问题实际上等价于求出图的最大环的长度,以及所有长度为 $2$ 的环加上其最长链。求这两者的最大值即可。求最长链到长度为 $2$ 的环,我们可以使用拓扑排序。
84+
85+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 `favorite` 的长度。
7886

7987
相似题目:[2360. 图中的最长环](/solution/2300-2399/2360.Longest%20Cycle%20in%20a%20Graph/README.md)
8088

@@ -87,7 +95,7 @@
8795
```python
8896
class Solution:
8997
def maximumInvitations(self, favorite: List[int]) -> int:
90-
def max_cycle(fa):
98+
def max_cycle(fa: List[int]) -> int:
9199
n = len(fa)
92100
vis = [False] * n
93101
ans = 0
@@ -106,13 +114,13 @@ class Solution:
106114
break
107115
return ans
108116

109-
def topological_sort(fa):
117+
def topological_sort(fa: List[int]) -> int:
110118
n = len(fa)
111119
indeg = [0] * n
112120
dist = [1] * n
113121
for v in fa:
114122
indeg[v] += 1
115-
q = deque([i for i, v in enumerate(indeg) if v == 0])
123+
q = deque(i for i, v in enumerate(indeg) if v == 0)
116124
while q:
117125
i = q.popleft()
118126
dist[fa[i]] = max(dist[fa[i]], dist[i] + 1)
@@ -314,10 +322,62 @@ func topologicalSort(fa []int) int {
314322

315323
### **TypeScript**
316324

317-
<!-- 这里可写当前语言的特殊实现逻辑 -->
318-
319325
```ts
326+
function maximumInvitations(favorite: number[]): number {
327+
return Math.max(maxCycle(favorite), topologicalSort(favorite));
328+
}
329+
330+
function maxCycle(fa: number[]): number {
331+
const n = fa.length;
332+
const vis: boolean[] = Array(n).fill(false);
333+
let ans = 0;
334+
for (let i = 0; i < n; ++i) {
335+
if (vis[i]) {
336+
continue;
337+
}
338+
const cycle: number[] = [];
339+
let j = i;
340+
for (; !vis[j]; j = fa[j]) {
341+
cycle.push(j);
342+
vis[j] = true;
343+
}
344+
for (let k = 0; k < cycle.length; ++k) {
345+
if (cycle[k] === j) {
346+
ans = Math.max(ans, cycle.length - k);
347+
}
348+
}
349+
}
350+
return ans;
351+
}
320352

353+
function topologicalSort(fa: number[]): number {
354+
const n = fa.length;
355+
const indeg: number[] = Array(n).fill(0);
356+
const dist: number[] = Array(n).fill(1);
357+
for (const v of fa) {
358+
++indeg[v];
359+
}
360+
const q: number[] = [];
361+
for (let i = 0; i < n; ++i) {
362+
if (indeg[i] === 0) {
363+
q.push(i);
364+
}
365+
}
366+
let ans = 0;
367+
while (q.length) {
368+
const i = q.pop()!;
369+
dist[fa[i]] = Math.max(dist[fa[i]], dist[i] + 1);
370+
if (--indeg[fa[i]] === 0) {
371+
q.push(fa[i]);
372+
}
373+
}
374+
for (let i = 0; i < n; ++i) {
375+
if (i === fa[fa[i]]) {
376+
ans += dist[i];
377+
}
378+
}
379+
return ans;
380+
}
321381
```
322382

323383
### **...**

solution/2100-2199/2127.Maximum Employees to Be Invited to a Meeting/README_EN.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,30 @@ The maximum number of employees that can be invited to the meeting is 4.
6161

6262
## Solutions
6363

64+
**Solution 1: Maximum Cycle in Graph + Longest Chain**
65+
66+
We observe that the employee's preference relationship in the problem can be regarded as a directed graph, which can be divided into multiple "base cycle inward trees". Each structure contains a cycle, and each node on the cycle is connected to a tree.
67+
68+
What is a "base cycle inward tree"? First, a base cycle tree is a directed graph with $n$ nodes and $n$ edges, and an inward tree means that in this directed graph, each node has exactly one outgoing edge. In this problem, each employee has exactly one favorite employee, so the constructed directed graph can be composed of multiple "base cycle inward trees".
69+
70+
<img alt="" src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/2100-2199/2127.Maximum%20Employees%20to%20Be%20Invited%20to%20a%20Meeting/images/05Dxh9.png"></p>
71+
72+
For this problem, we can find the length of the maximum cycle in the graph. Here we only need to find the length of the largest cycle, because if there are multiple cycles, they are not connected to each other, which does not meet the problem requirements.
73+
74+
In addition, for the size of the cycle equal to $2$, that is, there are two employees who like each other, then we can arrange these two employees together. If these two employees are each liked by other employees, then we only need to arrange the employees who like them next to them. If there are multiple such situations, we can arrange them all.
75+
76+
Therefore, the problem is actually equivalent to finding the length of the maximum cycle in the graph, and all cycles of length $2$ plus their longest chain. The maximum of these two can be found. To find the longest chain to the cycle of length $2$, we can use topological sorting.
77+
78+
The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array `favorite`.
79+
6480
<!-- tabs:start -->
6581

6682
### **Python3**
6783

6884
```python
6985
class Solution:
7086
def maximumInvitations(self, favorite: List[int]) -> int:
71-
def max_cycle(fa):
87+
def max_cycle(fa: List[int]) -> int:
7288
n = len(fa)
7389
vis = [False] * n
7490
ans = 0
@@ -87,13 +103,13 @@ class Solution:
87103
break
88104
return ans
89105

90-
def topological_sort(fa):
106+
def topological_sort(fa: List[int]) -> int:
91107
n = len(fa)
92108
indeg = [0] * n
93109
dist = [1] * n
94110
for v in fa:
95111
indeg[v] += 1
96-
q = deque([i for i, v in enumerate(indeg) if v == 0])
112+
q = deque(i for i, v in enumerate(indeg) if v == 0)
97113
while q:
98114
i = q.popleft()
99115
dist[fa[i]] = max(dist[fa[i]], dist[i] + 1)
Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
1-
class Solution:
2-
def maximumInvitations(self, favorite: List[int]) -> int:
3-
def max_cycle(fa):
4-
n = len(fa)
5-
vis = [False] * n
6-
ans = 0
7-
for i in range(n):
8-
if vis[i]:
9-
continue
10-
cycle = []
11-
j = i
12-
while not vis[j]:
13-
cycle.append(j)
14-
vis[j] = True
15-
j = fa[j]
16-
for k, v in enumerate(cycle):
17-
if v == j:
18-
ans = max(ans, len(cycle) - k)
19-
break
20-
return ans
21-
22-
def topological_sort(fa):
23-
n = len(fa)
24-
indeg = [0] * n
25-
dist = [1] * n
26-
for v in fa:
27-
indeg[v] += 1
28-
q = deque([i for i, v in enumerate(indeg) if v == 0])
29-
while q:
30-
i = q.popleft()
31-
dist[fa[i]] = max(dist[fa[i]], dist[i] + 1)
32-
indeg[fa[i]] -= 1
33-
if indeg[fa[i]] == 0:
34-
q.append(fa[i])
35-
return sum(dist[i] for i, v in enumerate(fa) if i == fa[fa[i]])
36-
37-
return max(max_cycle(favorite), topological_sort(favorite))
1+
class Solution:
2+
def maximumInvitations(self, favorite: List[int]) -> int:
3+
def max_cycle(fa: List[int]) -> int:
4+
n = len(fa)
5+
vis = [False] * n
6+
ans = 0
7+
for i in range(n):
8+
if vis[i]:
9+
continue
10+
cycle = []
11+
j = i
12+
while not vis[j]:
13+
cycle.append(j)
14+
vis[j] = True
15+
j = fa[j]
16+
for k, v in enumerate(cycle):
17+
if v == j:
18+
ans = max(ans, len(cycle) - k)
19+
break
20+
return ans
21+
22+
def topological_sort(fa: List[int]) -> int:
23+
n = len(fa)
24+
indeg = [0] * n
25+
dist = [1] * n
26+
for v in fa:
27+
indeg[v] += 1
28+
q = deque(i for i, v in enumerate(indeg) if v == 0)
29+
while q:
30+
i = q.popleft()
31+
dist[fa[i]] = max(dist[fa[i]], dist[i] + 1)
32+
indeg[fa[i]] -= 1
33+
if indeg[fa[i]] == 0:
34+
q.append(fa[i])
35+
return sum(dist[i] for i, v in enumerate(fa) if i == fa[fa[i]])
36+
37+
return max(max_cycle(favorite), topological_sort(favorite))
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
function maximumInvitations(favorite: number[]): number {
2+
return Math.max(maxCycle(favorite), topologicalSort(favorite));
3+
}
4+
5+
function maxCycle(fa: number[]): number {
6+
const n = fa.length;
7+
const vis: boolean[] = Array(n).fill(false);
8+
let ans = 0;
9+
for (let i = 0; i < n; ++i) {
10+
if (vis[i]) {
11+
continue;
12+
}
13+
const cycle: number[] = [];
14+
let j = i;
15+
for (; !vis[j]; j = fa[j]) {
16+
cycle.push(j);
17+
vis[j] = true;
18+
}
19+
for (let k = 0; k < cycle.length; ++k) {
20+
if (cycle[k] === j) {
21+
ans = Math.max(ans, cycle.length - k);
22+
}
23+
}
24+
}
25+
return ans;
26+
}
27+
28+
function topologicalSort(fa: number[]): number {
29+
const n = fa.length;
30+
const indeg: number[] = Array(n).fill(0);
31+
const dist: number[] = Array(n).fill(1);
32+
for (const v of fa) {
33+
++indeg[v];
34+
}
35+
const q: number[] = [];
36+
for (let i = 0; i < n; ++i) {
37+
if (indeg[i] === 0) {
38+
q.push(i);
39+
}
40+
}
41+
let ans = 0;
42+
while (q.length) {
43+
const i = q.pop()!;
44+
dist[fa[i]] = Math.max(dist[fa[i]], dist[i] + 1);
45+
if (--indeg[fa[i]] === 0) {
46+
q.push(fa[i]);
47+
}
48+
}
49+
for (let i = 0; i < n; ++i) {
50+
if (i === fa[fa[i]]) {
51+
ans += dist[i];
52+
}
53+
}
54+
return ans;
55+
}
Loading

0 commit comments

Comments
 (0)