lc802.找到最终的安全状态
约 552 字
预计阅读 2 分钟
染色法(DFS)
-
理解题目的意思:无论怎么走必定到达终点
-
也就是说该节点不能与环相连接
-
三色标记 label[i]表示当前结点的状态
-
0: 未访问
-
1: 可以到达环,或者在环中
-
2: 可以在有限步到达终点,不会进入到环。
-
T:O(m+n)
-
S:O(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
|
class Solution {
public:
// **理解题目的意思**:**无论怎么走**必定到达终点
// 也就是说该节点不能与环相连接
// 三色标记 label[i]表示当前结点的状态
// 0: 未访问
// 1: 可以到达环,或者在环中
// 2: 可以在有限步到达终点,不会进入到环。
// T:O(m+n)
// S:O(n)
vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> label(n, 0);
function <bool(int)> safe = [&](int x){
if(label[x] > 0){
return label[x] == 2;
}
label[x] = 1;
for(auto &y :graph[x]){
if(safe(y) == false){
return false;
}
}
label[x] = 2;
return true;
};
vector<int> res;
for(int i = 0; i < n; i++){
if(safe(i)){
res.push_back(i);
}
}
return res;
}
};
|
拓扑排序
- 将所有边翻转,原来终点(出度为0)反转后入度为零
- 在环内或者可以到达环的点,反转后经过拓扑排序入度肯定不为0.
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
|
class Solution {
public:
vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
int n = graph.size();
vector<vector<int>> rg(n, vector<int>());
vector<int> res;
vector<int> indegree(n, 0);
// 反向图
for(int i = 0; i < n; i++){
auto node = graph[i];
for(auto& to_node: node){
rg[to_node].push_back(i);
indegree[i] += 1;
}
}
// 拓扑排序
queue<int> que;
// 添加入度为0的点
for(int i = 0; i < n; i++){
if(indegree[i] == 0){
que.push(i);
}
}
while(!que.empty()){
int x = que.front();
que.pop();
for(auto& y: rg[x]){
indegree[y]--;
if(indegree[y] == 0){
que.push(y);
}
}
}
// 把最后入度为0的点添加到结果集。
for(int i = 0; i < n; i++){
if(indegree[i] == 0){
res.push_back(i);
}
}
return res;
}
};
|