CF1368E Ski Accidents 题解

思路

首先我们看到题中给出,这个图是一个 DAG,因此很容易的就可以想到拓扑排序。那么我们在思考一下,如何满足题目中给出的删除的点不超过 \(\frac{4}{7}n\) 的要求。我们可以举一个例子,看到下面的二叉树:

如果我们按照拓扑排序遍历,每次遍历到深度对 \(3\) 取模为 \(0\) 的节点,就删除。那么很显然,这个策略可以正常的分割出符合条件的链。同时,对于这个具有 \(7\) 个节点的图,他只删除了 \(4\) 个节点,满足题目 \(\frac{4}{7}n\) 的限制。

由此我们可以发现,无论怎么删除,都可以满足题目 \(\frac{4}{7}n\) 的限制。那么只要我们按照拓扑序遍历这个图,遇到深度超的就删除,就可以简单的水掉这一道紫题。

代码

拓扑序遍历即可,注意多测要清空。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

int n, m, u, v, d[200009], dp[200009];
vector<int> g[200009], ans, a[4];

int main() {
int t;
cin >> t;
while (t--) {
for (int i = 1; i <= n; i++) {
d[i] = 0;
dp[i] = 0;
g[i].clear();
}
ans.clear();
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> u >> v;
g[u].push_back(v);
d[v] += 1;
}
queue<int> q;
for (int i = 1; i <= n; i++) {
if (!d[i]) {
q.push(i);
dp[i] = 1;
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
if (dp[u] >= 3) {
dp[u] = 0;
ans.push_back(u);
}
for (int v: g[u]) {
d[v] -= 1;
dp[v]= max(dp[v], dp[u] + 1);
if (!d[v]) {
d[v] = -1;
q.push(v);
}
}
}
cout << ans.size() << endl;
for (int i: ans) {
cout << i << " ";
}
}
}


CF1368E Ski Accidents 题解
https://lixuannan.github.io/posts/28582
作者
CodingCow Lee
发布于
2024年2月23日
许可协议