Перечислить *все* гамильтоновы пути

Я знаю, что этот вопрос задавался раньше, но я не нашел ответа ни в одном из сообщений. Может ли кто-нибудь предложить мне алгоритм, который перечисляет ВСЕ гамильтоновы пути в графе?

Немного предыстории: я работаю над проблемой, в которой мне нужно перечислить каждый гамильтонов путь, провести некоторый анализ и вернуть результат. Для этого мне нужно иметь возможность перечислить все возможные гамильтоновы пути.

Спасибо.


person Darth.Vader    schedule 23.04.2011    source источник
comment
Вы пробовали простой поиск? БФС/ДФС? Насколько велики ваши графики?   -  person slezica    schedule 23.04.2011
comment
Сантьяго, спасибо за ответ. Мои графики маленькие (6-7 узлов). Я думал о BFS и DFS, но предполагаю, что BFS/DFS используются для поиска определенного ключа, а не для перечисления всех возможных путей. Как заставить BFS/DFS генерировать все возможные циклы..   -  person Darth.Vader    schedule 24.04.2011
comment
Обычный BFS/DFS останавливается после нахождения первого совпадающего ключа. Вам просто нужно изменить это, пройти весь график (если возможно) и отметить это как решение.   -  person slezica    schedule 24.04.2011


Ответы (4)


Используйте BFS/DFS, как предлагается, но не останавливайтесь на первом решении. Основное использование BFS/DFS (в данном случае) будет заключаться в том, чтобы найти все решения, вам нужно поставить ему условие, чтобы остановиться на первом.

person Máthé Endre-Botond    schedule 23.04.2011
comment
Спасибо. Не могли бы вы уточнить, что вы подразумеваете под «решением». Насколько я знаю, запуск DFS на графе просто даст последовательность посещенных узлов (например, A->B->C->D для графа с вершинами A, B, C, D). Но он никогда не будет «исследовать» ВСЕ возможные пути. Не могли бы вы уточнить? - person Darth.Vader; 24.04.2011
comment
И DFS, и BFS предоставят вам ВСЕ возможные пути, начинающиеся с определенного узла. Из этих гамильтоновых путей выходят те, длина которых точно равна размеру графа, и каждый узел существует ровно один раз. Итак, если у вас есть граф с 5 узлами и есть путь p1->p2->p3->p4->p5, это гамильтонов путь. Также обратите внимание, что вам придется начинать поиск с каждого узла. - person Máthé Endre-Botond; 24.04.2011
comment
Спасибо SinistraD, это очень полезно! - person Darth.Vader; 25.04.2011

Мой java-код: (абсолютно основан на рекурсивном методе)

алгоритм:

+ Начните с 1 точки, соединитесь с другой видимой точкой (чтобы сформировать путь).

+ удалить путь и рекурсивно найти новый путь в самой новой точке, пока не соединит все точки графика.

+ удалить путь и вернуться к исходному графику, если не удается сформировать путь Гамильтона из самой новой точки

public class HamiltonPath {
public static void main(String[] args){
    HamiltonPath obj = new HamiltonPath();

    int[][]x = {{0,1,0,1,0},  //Represent the graphs in the adjacent matrix forms
                {1,0,0,0,1},
                {0,0,0,1,0},
                {1,0,1,0,1},
                {0,1,0,1,0}};

    int[][]y = {{0,1,0,0,0,1},
                {1,0,1,0,0,1},
                {0,1,0,1,1,0},
                {0,0,1,0,0,0},
                {0,0,1,0,0,1},
                {1,1,0,0,1,0}};

    int[][]z = {{0,1,1,0,0,1},
                {1,0,1,0,0,0},
                {1,1,0,1,0,1},
                {0,0,1,0,1,0},
                {0,0,0,1,0,1},
                {1,0,1,0,1,0}};

    obj.allHamiltonPath(y);   //list all Hamiltonian paths of graph
    //obj.HamiltonPath(z,1);  //list all Hamiltonian paths start at point 1


}

static int len;
static int[]path;
static int count = 0;    

public void allHamiltonPath(int[][]x){  //List all possible Hamilton path in the graph
    len = x.length;
    path = new int[len];
    int i;
    for(i = 0;i<len;i++){ //Go through column(of matrix)
        path[0]=i+1;
        findHamiltonpath(x,0,i,0);
    }
}

public void HamiltonPath(int[][]x, int start){ //List all possible Hamilton path with fixed starting point
    len = x.length;
    path = new int[len];
    int i;
    for(i = start-1;i<start;i++){ //Go through row(with given column)
        path[0]=i+1;
        findHamiltonpath(x,0,i,0);
    }
}

private void findHamiltonpath(int[][]M,int x,int y,int l){

    int i;
        for(i=x;i<len;i++){         //Go through row

            if(M[i][y]!=0){      //2 point connect

                if(detect(path,i+1))// if detect a point that already in the path => duplicate 
                    continue;

                l++;            //Increase path length due to 1 new point is connected 
                path[l]=i+1;    //correspond to the array that start at 0, graph that start at point 1
                if(l==len-1){//Except initial point already count =>success connect all point
                    count++;   
                    if (count ==1)
                System.out.println("Hamilton path of graph: ");
                    display(path);
                    l--;
                    continue;
                }

                M[i][y]=M[y][i]=0;  //remove the path that has been get and
                findHamiltonpath(M,0,i,l); //recursively start to find new path at new end point
                l--;                // reduce path length due to the failure to find new path         
                M[i][y] = M[y][i]=1; //and tranform back to the inital form of adjacent matrix(graph)
            }
     }path[l+1]=0;    //disconnect two point correspond the failure to find the..   
}                     //possible hamilton path at new point(ignore newest point try another one)         

public void display(int[]x){

   System.out.print(count+" : ");
    for(int i:x){
        System.out.print(i+" ");
    }
        System.out.println();   
}

private boolean detect(int[]x,int target){ //Detect duplicate point in Halmilton path 
    boolean t=false;                        
    for(int i:x){
        if(i==target){
            t = true;
            break;
        }
    }
    return t;
}  

}

person Tranquocbinh333    schedule 25.08.2011

Решение в Python3:

def hamiltonians(G, vis = []):
    if not vis:
        for n in G:
            for p in hamiltonians(G, [n]):
                yield p
    else:
        dests = set(G[vis[-1]]) - set(vis)
        if not dests and len(vis) == len(G):
            yield vis
        for n in dests:
            for p in hamiltonians(G, vis + [n]):
                yield p
G = {'a' : 'bc', 'b' : 'ad', 'c' : 'b', 'd' : 'ac'}
print(list(hamiltonians(G)))
person Björn Lindqvist    schedule 08.01.2018

Исчерпывающий поиск в глубину даст вам ответ. Я только что закончил писать о реализации Java для этой проблемы (включая код):

http://puzzledraccoon.wordpress.com/2012/06/07/how-to-cool-a-data-center/

person Miro Lehtonen    schedule 08.09.2014