图论中环的判断
Posted czsharecode
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论中环的判断相关的知识,希望对你有一定的参考价值。
无向图环的判断
- 并查集判断
- 如果两个结点父亲相同,并且两个结点之间有边相连,则存在环
def init();
def find(int x);//必须进行路径压缩
def merge(int x, int y);
if(find(x) == find(y) && G[x][y] != 0){ cycle = true;}
else merge(x,y);
- DFS判断
- dfs的过程中如果遇到已经访问过的点,并且这个点不是自己的直接父亲,那么就必然存在环
public class Cycle {
?????private boolean[] marked;
?????private boolean hasCycle;
?????public Cycle(Graph G) {???????
?????????this.marked = new boolean[G.V()];
?????????this.hasCycle = false;
?????????for(int i=1; i<G.V(); i++) {
??????????????if(!marked[i]) {
??????????????????//默认第一个结点没有父节点
??????????????????dfs(G, i, -1);
??????????????}
?????????}
?????}
?????private void dfs(Graph G, int cur, int pre) {
?????????marked[cur] = true;
?????????for(Integer nxt : G.adj(cur)) {
??????????????if(!marked[nxt]) {
??????????????????dfs(G, nxt, cur);
??????????????}
??????????????else if(nxt != pre) {
??????????????????this.hasCycle = true;
??????????????}
?????????}
?????}
?????public boolean hasCycle() {return this.hasCycle;}
有向图环的判断
- 单纯判断
- 在dfs的过程中,把dfs经过的结点全部保存在一个栈上(或者直接用布尔数组进行标记),然后每当经过一个结点时,判断当前结点是否在栈上,是则有环
- 事实上其实质就是,在dfs的过程中又遇到了已经访问过的点,则必然存在环
- 问题:为什么这里不需要考虑:如果该点已经被访问过并且该点是父亲结点的情况呢?无向图中不是考虑了吗?
- 这里是有向图,如果从孩子结点能有边返回到父亲结点,那么显然这两者之间存在环。
- 记录环中的结点
- 需要用栈记录当前路径经过的结点,并且记录每个结点的父亲结点,也就是说记录一下在当前路径中,当前结点是哪一个结点来的。
- 如果遇到了一个结点已经被访问过并且在栈上, 那么必然存在一个有向环。从这个结点出发,一直找当前结点的父结点,记录到结果容器里面,直到又遇到这个结点。
- 注意这个dfs路径记录栈,当某一次dfs要返回的时候(此时已经确定在 这一遍dfs中无法找到环),则沿途回溯取消所有结点在栈上的标记(把布尔数组置为false)
public class DiCycle {
?????private boolean[] marked;//记录结点是否访问过
?????private int[] edgeTo;//记录该结点的父节点
?????private Stack<Integer> cycle;
?????private boolean[] onStack;//记录当前访问路径上的结点
????
?????public DiCycle(Digraph G) {
?????????marked = new boolean[G.V()];
?????????edgeTo? = new int[G.V()];
?????????cycle = new Stack<Integer>();
?????????onStack = new boolean[G.V()];
?????????for(int i=0; i<G.V(); i++) {
??????????????if(!marked[i]) {
??????????????????dfs(G, i);
??????????????}
?????????}
?????}
?????private void dfs(Digraph G, int v) {
?????????// TODO Auto-generated method stub
?????????marked[v] = true;
?????????onStack[v] = true;
?????????for(Integer w : G.adj(v)) {
??????????????if(this.hasCycle()) return ;
??????????????else if(!marked[w]) {
??????????????????edgeTo[w] = v;
??????????????????dfs(G , w);
??????????????}
??????????????else if(onStack[w]) {
??????????????????for(int x=v; x!=w; x=edgeTo[x]) {
???????????????????????cycle.push(x);
??????????????????}
??????????????????cycle.push(w);
??????????????????cycle.push(v);
??????????????}
?????????}
?????????onStack[v] = false;//回溯时取消其在栈上,相当于清空栈,便于下一次dfs???????
?????}
?????public void showCycle() {
?????????if(!this.hasCycle()) System.out.println("no cycle...");
?????????Stack<Integer> s = new Stack<Integer>();
?????????s = (Stack<Integer>) cycle.clone();
?????????while(!s.isEmpty()) {
??????????????System.out.println(s.peek());
??????????????s.pop();
}
?????}
以上是关于图论中环的判断的主要内容,如果未能解决你的问题,请参考以下文章