Algorithm 帮助Donalds B.Johnson';s算法,我无法理解伪代码(第二部分)

Algorithm 帮助Donalds B.Johnson';s算法,我无法理解伪代码(第二部分),algorithm,graph,cycle,pseudocode,Algorithm,Graph,Cycle,Pseudocode,我无法理解唐纳德·约翰逊(Donald Johnson)发表的论文中关于在图中寻找圈(回路)的某一部分 更具体地说,我无法理解以下伪代码行中提到的矩阵Ak是什么: Ak:=具有最小值的强分量K的邻接结构 由{s,s+1,….n}诱导的G的子图中的顶点 更糟糕的是,在is mentins“for i in Vk do”之后的一些行没有声明Vk是什么 据我所知,我们有以下几点: 1) 通常,强组件是一个图的子图,其中该子图的每个节点都有一条到该子图任何节点的路径(换句话说,您可以从该子图的任何其他节

我无法理解唐纳德·约翰逊(Donald Johnson)发表的论文中关于在图中寻找圈(回路)的某一部分

更具体地说,我无法理解以下伪代码行中提到的矩阵Ak是什么:

Ak:=具有最小值的强分量K的邻接结构 由{s,s+1,….n}诱导的G的子图中的顶点

更糟糕的是,在is mentins“for i in Vk do”之后的一些行没有声明Vk是什么

据我所知,我们有以下几点: 1) 通常,强组件是一个图的子图,其中该子图的每个节点都有一条到该子图任何节点的路径(换句话说,您可以从该子图的任何其他节点访问该子图的任何节点)

2) 由节点列表导出的子图是 包含所有这些节点以及连接这些节点的所有边的图形。 本文给出的数学定义是:如果W是V的子集,F=(W,{u,y)| u,y在W中,(u,y在E中)}),其中u,y是边,E是图中所有边的集合,W是节点的集合,则F是由W导出的G的子图

3) 在代码实现中,节点由整数1…n命名

4) 我怀疑Vk是强组件K的节点集

现在我们来讨论这个问题,假设我们有一个图G=(V,E),其中V={1,2,3,4,5,6,7,8,9},它可以被分成3个强分量,即SC1={1,4,7,8}SC2={2,3,9}SC3={5,6}(及其边)

有人能给我举一个s=1,s=2,s=5的例子吗?如果根据代码是Vk和Ak呢

伪代码在我的上一个问题中

该文件可在

提前感谢您

它是有效的!在of中,我假设
A
是an。相反,它似乎表示an。在下面实现的示例中,顶点编号为{0,1,2},产生以下电路

附录:如本文所述,该算法规定
unblock()
应删除具有值
w
的元素,而不是具有索引
w
的元素

list.remove(Integer.valueOf(w));
样本输出:

0 1 0 0 1 2 0 0 2 0 0 2 1 0 1 0 1 1 0 2 1 1 2 0 1 1 2 1 2 0 1 2 2 0 2 2 1 0 2 2 1 2 我请求@trashgod的代码修复
unblock()
中抛出的异常。本质上,算法声明元素
w
(不是索引)将从列表中删除。上面的代码使用
list.remove(w)
,它将
w
视为索引

我的请求被拒绝了!不知道为什么,因为我已经在一个由20000个节点和70000个边缘组成的网络上测试了上述修改,并且没有崩溃

我还修改了Johnson的算法,使其更适用于无向图。如果有人需要这些修改,请与我联系

下面是我的
unblock()
代码

private void unblock(int u){
阻塞的[u]=假;
列表=b.get(u);
int w;
for(int-iw=0;iw
@trashgod,您的示例输出包含循环置换的循环。 例如,0-1-0和1-0-1是相同的 实际上,输出应该只包含5个周期,即。 0 1 0, 0 2 0, 0 1 2 0, 0 2 1 0, 1,2,1

约翰逊论文解释了什么是周期: 如果一个电路不是另一个电路的循环置换,那么两个基本电路是不同的。 ' 还可以检查wolfram页面:这也为相同的输入输出5个周期


以下变体产生独特的循环。基于此,它由提供的

代码:

所有循环,供参考:

0 1 0
0 1 2 0
0 2 0
0 2 1 0
1 0 1
1 0 2 1
1 2 0 1
1 2 1
2 0 1 2
2 0 2
2 1 0 2
2 1 2

@斯塔克:我希望不是!套用克努特的话:“小心上面代码中的bug;我只是试过,没有证明它是正确的。“@trashgood谢谢你的好意和非常有用的帮助@stacker基本上是我的MSC论文的一小部分,但没有问题,因为我已经写了大部分代码,而且我使用完全不同的结构。我还没有测试你的代码,但仍然有一个小问题。Ak指的是强组件的子图(在您的示例中,网络都是一个SCC..但是如果它可以被划分为2个SCC会发生什么?那么Ak将如何呢?)仍然是一个大问号。我的想法是,可能(我必须测试它以检查正确性)Ak是包含s的子图的邻接列表,但是从这个SCC到所有其他SCC的边都被删除了。例如,假设{0,1,2}是你的示例图,它与{3,4}相连,有一条2->3的边,那么A0,A1,A2将是(你已经给出的)邻接列表加上没有2->3的边的新的邻接列表。所有关于SCC的麻烦都是因为你可以把G分成更小的一个,从而提高算法的性能(因为算法的复杂度为O(E*C),其中C=循环数。哪个C增长2^n,其中n是节点数…)无论如何,万分感谢你的帮助!@Gedde:我添加了一个,上面引用了它;注意,代码修正为+1,用于发现这个问题;我更新了我的类似版本。编辑请求可能看起来像是试图绕过评论阈值,但这是一个很好的答案。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
 * @see https://en.wikipedia.org/wiki/Johnson%27s_algorithm
 * @see https://stackoverflow.com/questions/2908575
 * @see https://stackoverflow.com/questions/2939877
 * @see http://en.wikipedia.org/wiki/Adjacency_matrix
 * @see http://en.wikipedia.org/wiki/Adjacency_list
 */
public final class CircuitFinding {

    final Stack<Integer> stack = new Stack<Integer>();
    final Map<Integer, List<Integer>> a;
    final List<List<Integer>> b;
    final boolean[] blocked;
    final int n;
    Integer s;

    public static void main(String[] args) {
        List<List<Integer>> a = new ArrayList<List<Integer>>();
        a.add(new ArrayList<Integer>(Arrays.asList(1, 2)));
        a.add(new ArrayList<Integer>(Arrays.asList(0, 2)));
        a.add(new ArrayList<Integer>(Arrays.asList(0, 1)));
        CircuitFinding cf = new CircuitFinding(a);
        cf.find();
    }

    /**
     * @param a adjacency structure of strong component K with least vertex in
     * subgraph of G induced by {s, s + 1, n};
     */
    public CircuitFinding(List<List<Integer>> A) {
        this.a = new HashMap<Integer, List<Integer>>(A.size());
        for (int i = 0; i < A.size(); i++) {
            this.a.put(i, new ArrayList<Integer>());
            for (int j : A.get(i)) {
                this.a.get(i).add(j);
            }
        }
        n = a.size();
        blocked = new boolean[n];
        b = new ArrayList<List<Integer>>();
        for (int i = 0; i < n; i++) {
            b.add(new ArrayList<Integer>());
        }
    }

    private void unblock(int u) {
        blocked[u] = false;
        List<Integer> list = b.get(u);
        for (int w : list) {
            //delete w from B(u);
            list.remove(Integer.valueOf(w));
            if (blocked[w]) {
                unblock(w);
            }
        }
    }

    private boolean circuit(int v) {
        boolean f = false;
        stack.push(v);
        blocked[v] = true;
        L1:
        for (int w : a.get(v)) {
            if (w == s) {
                //output circuit composed of stack followed by s;
                for (int i : stack) {
                    System.out.print(i + " ");
                }
                System.out.println(s);
                f = true;
            } else if (!blocked[w]) {
                if (circuit(w)) {
                    f = true;
                }
            }
        }
        L2:
        if (f) {
            unblock(v);
        } else {
            for (int w : a.get(v)) {
                //if (v∉B(w)) put v on B(w);
                if (!b.get(w).contains(v)) {
                    b.get(w).add(v);
                }
            }
        }
        v = stack.pop();
        return f;
    }

    public void find() {
        s = 0;
        while (s < n) {
            if (!a.isEmpty()) {
                //s := least vertex in V;
                L3:
                for (int i : a.keySet()) {
                    b.get(i).clear();
                    blocked[i] = false;
                }
                circuit(s);
                a.remove(s);
                for (Integer j : a.keySet()) {
                    if (a.get(j).contains(s)) {
                        a.get(j).remove(s);
                    }
                }
                s++;
            } else {
                s = n;
            }
        }
    }
}
0 1 0
0 1 2 0
0 2 0
0 2 1 0
1 2 1
0 1 0
0 1 2 0
0 2 0
0 2 1 0
1 0 1
1 0 2 1
1 2 0 1
1 2 1
2 0 1 2
2 0 2
2 1 0 2
2 1 2