53
53
54
54
<!-- 这里可写通用的实现逻辑 -->
55
55
56
+ ** 方法一:拓扑排序**
57
+
56
58
出度为零的点是安全的,如果一个点** 只能** 到达安全的点,那么它同样是安全的,所以问题转换成了拓扑排序。
57
59
60
+ 我们可以将图中所有边反向,得到一个反图,然后在反图上运行拓扑排序。
61
+
62
+ 时间复杂度 $O(n+m)$,其中 $n$ 表示图中的点数,$m$ 表示图中的边数。
63
+
64
+ ** 方法二:DFS + 三色标记法**
65
+
66
+ 若起始节点位于一个环内,或者能到达一个环,则该节点不是安全的。否则,该节点是安全的。
67
+
68
+ - 白色(用 0 表示):该节点尚未被访问;
69
+ - 灰色(用 1 表示):该节点位于递归栈中,或者在某个环上;
70
+ - 黑色(用 2 表示):该节点搜索完毕,是一个安全节点。
71
+
58
72
<!-- tabs:start -->
59
73
60
74
### ** Python3**
64
78
``` python
65
79
class Solution :
66
80
def eventualSafeNodes (self , graph : List[List[int ]]) -> List[int ]:
67
- n = len (graph )
68
- outDegree = [len (vs) for vs in graph]
69
- revGraph = defaultdict( list )
70
- for u, vs in enumerate (graph) :
71
- for v in vs:
72
- revGraph[v].append(u )
73
- q = deque([i for i, d in enumerate (outDegree ) if d == 0 ])
81
+ rg = defaultdict( list )
82
+ indeg = [0 ] * len ( graph)
83
+ for i, vs in enumerate (graph):
84
+ for j in vs :
85
+ rg[j].append(i)
86
+ indeg[i] = len (vs )
87
+ q = deque([i for i, v in enumerate (indeg ) if v == 0 ])
74
88
while q:
75
- for u in revGraph[q.popleft()]:
76
- outDegree[u] -= 1
77
- if outDegree[u] == 0 :
78
- q.append(u)
79
- return [i for i, d in enumerate (outDegree) if d == 0 ]
89
+ i = q.popleft()
90
+ for j in rg[i]:
91
+ indeg[j] -= 1
92
+ if indeg[j] == 0 :
93
+ q.append(j)
94
+ return [i for i, v in enumerate (indeg) if v == 0 ]
95
+ ```
96
+
97
+ ``` python
98
+ class Solution :
99
+ def eventualSafeNodes (self , graph : List[List[int ]]) -> List[int ]:
100
+ def dfs (i ):
101
+ if color[i]:
102
+ return color[i] == 2
103
+ color[i] = 1
104
+ for j in graph[i]:
105
+ if not dfs(j):
106
+ return False
107
+ color[i] = 2
108
+ return True
109
+
110
+ n = len (graph)
111
+ color = [0 ] * n
112
+ return [i for i in range (n) if dfs(i)]
80
113
```
81
114
82
115
### ** Java**
@@ -87,39 +120,71 @@ class Solution:
87
120
class Solution {
88
121
public List<Integer > eventualSafeNodes (int [][] graph ) {
89
122
int n = graph. length;
90
- int [] outDegrees = new int [n];
91
- Queue <Integer > queue = new ArrayDeque<> () ;
92
- List< List< Integer > > revGraph = new ArrayList<> ();
93
- for ( int i = 0 ; i < n; i ++ ) {
94
- revGraph . add( new ArrayList<> ());
95
- }
96
- for (int u = 0 ; u < n; u ++ ) {
97
- for (int v : graph[u ]) {
98
- revGraph . get(v) . add(u );
123
+ int [] indeg = new int [n];
124
+ List <Integer >[] rg = new List [n] ;
125
+ for ( int i = 0 ; i < n; ++ i) {
126
+ rg[i] = new ArrayList<> ();
127
+ }
128
+ Deque< Integer > q = new ArrayDeque<> ();
129
+ for (int i = 0 ; i < n; ++ i ) {
130
+ for (int j : graph[i ]) {
131
+ rg[j] . add(i );
99
132
}
100
- outDegrees[u ] = graph[u ]. length;
101
- if (outDegrees[u ] == 0 ) {
102
- queue . offer(u );
133
+ indeg[i ] = graph[i ]. length;
134
+ if (indeg[i ] == 0 ) {
135
+ q . offer(i );
103
136
}
104
137
}
105
-
106
- while (! queue. isEmpty()) {
107
- int v = queue. poll();
108
- for (int u : revGraph. get(v)) {
109
- if (-- outDegrees[u] == 0 ) {
110
- queue. offer(u);
138
+ while (! q. isEmpty()) {
139
+ int i = q. pollFirst();
140
+ for (int j : rg[i]) {
141
+ if (-- indeg[j] == 0 ) {
142
+ q. offer(j);
111
143
}
112
144
}
113
145
}
146
+ List<Integer > ans = new ArrayList<> ();
147
+ for (int i = 0 ; i < n; ++ i) {
148
+ if (indeg[i] == 0 ) {
149
+ ans. add(i);
150
+ }
151
+ }
152
+ return ans;
153
+ }
154
+ }
155
+ ```
156
+
157
+ ``` java
158
+ class Solution {
159
+ private int [] color;
160
+ private int [][] g;
114
161
162
+ public List<Integer > eventualSafeNodes (int [][] graph ) {
163
+ int n = graph. length;
164
+ color = new int [n];
165
+ g = graph;
115
166
List<Integer > ans = new ArrayList<> ();
116
- for (int i = 0 ; i < n; i ++ ) {
117
- if (outDegrees[i] == 0 ) {
167
+ for (int i = 0 ; i < n; ++ i ) {
168
+ if (dfs(i) ) {
118
169
ans. add(i);
119
170
}
120
171
}
121
172
return ans;
122
173
}
174
+
175
+ private boolean dfs (int i ) {
176
+ if (color[i] > 0 ) {
177
+ return color[i] == 2 ;
178
+ }
179
+ color[i] = 1 ;
180
+ for (int j : g[i]) {
181
+ if (! dfs(j)) {
182
+ return false ;
183
+ }
184
+ }
185
+ color[i] = 2 ;
186
+ return true ;
187
+ }
123
188
}
124
189
```
125
190
@@ -128,34 +193,59 @@ class Solution {
128
193
``` go
129
194
func eventualSafeNodes (graph [][]int ) []int {
130
195
n := len (graph)
131
- outDegree := make ([]int , n)
132
- revGraph := make ([][]int , n)
133
- queue := make ([]int , 0 )
134
- ans := make ([]int , 0 )
135
-
136
- for u , vs := range graph {
137
- for _ , v := range vs {
138
- revGraph[v] = append (revGraph[v], u)
196
+ indeg := make ([]int , n)
197
+ rg := make ([][]int , n)
198
+ q := []int {}
199
+ for i , vs := range graph {
200
+ for _ , j := range vs {
201
+ rg[j] = append (rg[j], i)
139
202
}
140
- outDegree[u ] = len (vs)
141
- if outDegree[u ] == 0 {
142
- queue = append (queue, u )
203
+ indeg[i ] = len (vs)
204
+ if indeg[i ] == 0 {
205
+ q = append (q, i )
143
206
}
144
207
}
145
-
146
- for len (queue) > 0 {
147
- v := queue[0 ]
148
- queue = queue[1 :]
149
- for _ , u := range revGraph[v] {
150
- outDegree[u]--
151
- if outDegree[u] == 0 {
152
- queue = append (queue, u)
208
+ for len (q) > 0 {
209
+ i := q[0 ]
210
+ q = q[1 :]
211
+ for _ , j := range rg[i] {
212
+ indeg[j]--
213
+ if indeg[j] == 0 {
214
+ q = append (q, j)
153
215
}
154
216
}
155
217
}
218
+ ans := []int {}
219
+ for i , v := range indeg {
220
+ if v == 0 {
221
+ ans = append (ans, i)
222
+ }
223
+ }
224
+ return ans
225
+ }
226
+ ```
156
227
157
- for i , d := range outDegree {
158
- if d == 0 {
228
+ ``` go
229
+ func eventualSafeNodes (graph [][]int ) []int {
230
+ n := len (graph)
231
+ color := make ([]int , n)
232
+ var dfs func (int ) bool
233
+ dfs = func (i int ) bool {
234
+ if color[i] > 0 {
235
+ return color[i] == 2
236
+ }
237
+ color[i] = 1
238
+ for _ , j := range graph[i] {
239
+ if !dfs (j) {
240
+ return false
241
+ }
242
+ }
243
+ color[i] = 2
244
+ return true
245
+ }
246
+ ans := []int {}
247
+ for i := range graph {
248
+ if dfs (i) {
159
249
ans = append (ans, i)
160
250
}
161
251
}
@@ -168,36 +258,120 @@ func eventualSafeNodes(graph [][]int) []int {
168
258
``` cpp
169
259
class Solution {
170
260
public:
171
- vector<int > eventualSafeNodes(vector<vector<int >> & graph) {
261
+ vector<int > eventualSafeNodes(vector<vector<int >>& graph) {
172
262
int n = graph.size();
173
- vector<vector<int >> revGraph(n);
174
- vector<int > outDegree(n);
263
+ vector<int > indeg(n);
264
+ vector<vector<int >> rg(n);
265
+ queue<int > q;
175
266
for (int i = 0; i < n; ++i)
176
267
{
177
- outDegree [ i ] += graph[ i] .size( );
178
- for (int j : graph[ i] )
179
- revGraph [ j ] .push_back (i);
268
+ for (int j : graph[ i] ) rg [ j ] .push_back(i );
269
+ indeg [ i ] = graph[ i] .size();
270
+ if (indeg [ i ] == 0) q.push (i);
180
271
}
181
- queue<int > q;
182
- for (int i = 0; i < n; ++i)
183
- if (outDegree[ i] == 0)
184
- q.push(i);
185
272
while (!q.empty())
186
273
{
187
274
int i = q.front();
188
275
q.pop();
189
- for (int j : revGraph[ i] )
190
- {
191
- if (--outDegree[ j] == 0)
192
- q.push(j);
193
- }
276
+ for (int j : rg[ i] ) if (--indeg[ j] == 0) q.push(j);
194
277
}
195
278
vector<int > ans;
196
- for (int i = 0; i < n; ++i)
197
- if (outDegree[ i] == 0)
198
- ans.push_back(i);
279
+ for (int i = 0; i < n; ++i) if (indeg[ i] == 0) ans.push_back(i);
280
+ return ans;
281
+ }
282
+ };
283
+ ```
284
+
285
+ ```cpp
286
+ class Solution {
287
+ public:
288
+ vector<int> color;
289
+
290
+ vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
291
+ int n = graph.size();
292
+ color.assign(n, 0);
293
+ vector<int> ans;
294
+ for (int i = 0; i < n; ++i) if (dfs(i, graph)) ans.push_back(i);
199
295
return ans;
200
296
}
297
+
298
+ bool dfs(int i, vector<vector<int>>& g) {
299
+ if (color[i]) return color[i] == 2;
300
+ color[i] = 1;
301
+ for (int j : g[i]) if (!dfs(j, g)) return false;
302
+ color[i] = 2;
303
+ return true;
304
+ }
305
+ };
306
+ ```
307
+
308
+ ### ** JavaScript**
309
+
310
+ ``` js
311
+ /**
312
+ * @param {number[][]} graph
313
+ * @return {number[]}
314
+ */
315
+ var eventualSafeNodes = function (graph ) {
316
+ const n = graph .length ;
317
+ const rg = new Array (n).fill (0 ).map (() => new Array ());
318
+ const indeg = new Array (n).fill (0 );
319
+ const q = [];
320
+ for (let i = 0 ; i < n; ++ i) {
321
+ for (let j of graph[i]) {
322
+ rg[j].push (i);
323
+ }
324
+ indeg[i] = graph[i].length ;
325
+ if (indeg[i] == 0 ) {
326
+ q .push (i);
327
+ }
328
+ }
329
+ while (q .length ) {
330
+ const i = q .shift ();
331
+ for (let j of rg[i]) {
332
+ if (-- indeg[j] == 0 ) {
333
+ q .push (j);
334
+ }
335
+ }
336
+ }
337
+ let ans = [];
338
+ for (let i = 0 ; i < n; ++ i) {
339
+ if (indeg[i] == 0 ) {
340
+ ans .push (i);
341
+ }
342
+ }
343
+ return ans;
344
+ };
345
+ ```
346
+
347
+ ``` js
348
+ /**
349
+ * @param {number[][]} graph
350
+ * @return {number[]}
351
+ */
352
+ var eventualSafeNodes = function (graph ) {
353
+ const n = graph .length ;
354
+ const color = new Array (n).fill (0 );
355
+ function dfs (i ) {
356
+ if (color[i]) {
357
+ return color[i] == 2 ;
358
+ }
359
+ color[i] = 1 ;
360
+ for (const j of graph[i]) {
361
+ if (! dfs (j)) {
362
+ return false ;
363
+ }
364
+ }
365
+ color[i] = 2 ;
366
+ return true ;
367
+ }
368
+ let ans = [];
369
+ for (let i = 0 ; i < n; ++ i) {
370
+ if (dfs (i)) {
371
+ ans .push (i);
372
+ }
373
+ }
374
+ return ans;
201
375
};
202
376
```
203
377
0 commit comments