Google – Print All Cycles in Graph
很简单的题,但是对于是否会出现无限循环?或者发现cycle后要不要把visit[]置1(表示已经结束)?这两个想来想去想不清楚的问题,赤裸裸的证明了我recursion和backtracking根本就没想明白过….
首先会不会出现无限循环?
答案是no. 不会出现无限循环. 因为如果找到了一个cycle,也就是回到了某个visit过但是还没有结束的vertex,我们做的是输出cycle后return,而不是继续往下找,如果继续往下找就会出现无限循环了。所以无论图里有几个cycle,都不会出现无限循环的情况。
其次要不要置1?
答案也是no. 找到cycle后不能把visit[]置1!除非题目假设了graph里只有一个cycle,否则想象一下有一个点,从这个点出发,左边有一个cycle,右边有一个cycle,像∞这样,(或者上下各有个cycle,那就像8这样)。那么如果找到一个cycle后就把visit[]置1,那第二个cycle就没法被发现了。
Read full article from Google – Print All Cycles in Graph
很简单的题,但是对于是否会出现无限循环?或者发现cycle后要不要把visit[]置1(表示已经结束)?这两个想来想去想不清楚的问题,赤裸裸的证明了我recursion和backtracking根本就没想明白过….
首先会不会出现无限循环?
答案是no. 不会出现无限循环. 因为如果找到了一个cycle,也就是回到了某个visit过但是还没有结束的vertex,我们做的是输出cycle后return,而不是继续往下找,如果继续往下找就会出现无限循环了。所以无论图里有几个cycle,都不会出现无限循环的情况。
其次要不要置1?
答案也是no. 找到cycle后不能把visit[]置1!除非题目假设了graph里只有一个cycle,否则想象一下有一个点,从这个点出发,左边有一个cycle,右边有一个cycle,像∞这样,(或者上下各有个cycle,那就像8这样)。那么如果找到一个cycle后就把visit[]置1,那第二个cycle就没法被发现了。
public
List<List<Integer>> allCycles(Map<Integer, Set<Integer>> graph) {
List<List<Integer>> result =
new
ArrayList<>();
if
(graph ==
null
|| graph.isEmpty()) {
return
result;
}
int
[] visited =
new
int
[graph.size()];
for
(
int
v : graph.keySet()) {
if
(visited[v] ==
0
) {
List<Integer> tmp =
new
ArrayList<>();
dfs(graph, v, visited, result, tmp);
}
}
return
result;
}
private
void
dfs(Map<Integer, Set<Integer>> graph,
int
v,
int
[] visited, List<List<Integer>> result, List<Integer> tmp) {
if
(visited[v] == -
1
) {
List<Integer> cycle =
new
LinkedList<>();
cycle.add(v);
for
(
int
i = tmp.size() -
1
; i >=
0
; i--) {
cycle.add(
0
, tmp.get(i));
if
(tmp.get(i) == v) {
break
;
}
}
result.add(
new
ArrayList<>(cycle));
return
;
}
if
(visited[v] ==
1
) {
return
;
}
visited[v] = -
1
;
tmp.add(v);
for
(
int
adj : graph.get(v)) {
dfs(graph, adj, visited, result, tmp);
}
tmp.remove(tmp.size() -
1
);
visited[v] =
1
;
}