помогите в алгоритме Дональдса Б. Джонсона, я не могу понять псевдо-код (Часть II)
Я не могу понять определенную часть статьи, опубликованной Дональдом Джонсоном о нахождении циклов (схем) в графе.
более конкретно я не могу понять, что такое матрица Ak, которая упоминается в следующей строке псевдо-кода:
Ak:=структура смежности сильного компонента K с наименьшим вершина в подграфе G, индуцированная {s, s+1,....n};
сделать хуже некоторые строки после того, как ментины "за Я в ВК делаю" без объявив, что такое Вконтакте...
насколько я понимаю, у нас есть следующее: 1) в общем случае сильной составляющей является подграф графа, в котором для каждого узла этого подграфа существует путь к любому узлу подграфа (другими словами, вы можете получить доступ к любому узлу подграфа из любого другого узла подграфа)
2) суб-графика индуцированной по списку узлов график, содержащий все эти узлы плюс все ребра, соединяющие эти узлы. в статье математическое определение: "F-подграф G, индуцированный W, если W-подмножество V и F = (W,{u,y)|u,y в W и (u,y) в E)}), где u , y-ребра, E-множество всех ребер в графе, W-множество узлов.
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 в соответствии с кодом?
псевдо код в мой предыдущий вопрос понимание псевдокода в алгоритме Дональда Б. Джонсона
и бумагу можно найти на понимание псевдокод в алгоритме Дональда Б. Джонсона
спасибо заранее
4 ответов
это работает! В ранее итерации на алгоритм Джонсона, Я предполагал, что A
был матрица смежности. Вместо этого он, похоже, представляет список смежности. В этом примере, реализованном ниже, вершины {a, b, c} пронумерованы {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
по умолчанию, программа начинается с s = 0
; реализации s := least vertex in V
в качестве оптимизации остается. Показано изменение, которое производит только уникальные циклы здесь.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
/**
* @see http://dutta.csc.ncsu.edu/csc791_spring07/wrap/circuits_johnson.pdf
* @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 List<List<Integer>> a;
final List<List<Integer>> b;
final boolean[] blocked;
final int n;
int 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 = a;
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() {
while (s < n) {
if (a != null) {
//s := least vertex in V;
L3:
circuit(s);
s++;
} else {
s = n;
}
}
}
}
Я сумбитредактировать запрос на код @trashgod, чтобы исправить исключение, брошенное в unblock()
. По сути, алгоритм утверждает, что элемент w
(т. е. не индекс) должен быть удален из списка. Код выше используется list.remove(w)
, что относится к w
как индекс.
мой редактировать запрос был отклонен! Не уверен, почему, потому что я протестировал вышеизложенное с моей модификацией в сети из 20 000 узлов и 70 000 ребер и он не разбивается.
Я также изменил алгоритм Джонсона, чтобы быть более адаптированным к неориентированным графам. Если кто-нибудь хочет эти изменения, пожалуйста, свяжитесь со мной.
ниже мой код unblock()
.
private void unblock(int u) {
blocked[u] = false;
List<Integer> list = b.get(u);
int w;
for (int iw=0; iw < list.size(); iw++) {
w = Integer.valueOf(list.get(iw));
//delete w from B(u);
list.remove(iw);
if (blocked[w]) {
unblock(w);
}
}
}
@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 циклов для того же самого вход.
http://demonstrations.wolfram.com/EnumeratingCyclesOfADirectedGraph/
следующее изменение производит уникальные циклы. Основываясь на этом пример, он адаптирован из ответ предоставленный @user1406062.
код:
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