Java 求部分定向图中所有可能的哈密顿圈

Java 求部分定向图中所有可能的哈密顿圈,java,hamiltonian-cycle,Java,Hamiltonian Cycle,这是我在图中求哈密顿圈的算法: private SolutionArray solution; private int V, pathCount; private int[] path; private int[][] graph; /** * Constructor */ public ConcreteSolver() { solution = new SolutionArray(); } @Override public SolutionArray solve(PathMat

这是我在图中求哈密顿圈的算法:

private SolutionArray solution;
private int V, pathCount;
private int[] path;
private int[][] graph;

/**
 * Constructor
 */
public ConcreteSolver() {
    solution = new SolutionArray();
}

@Override
public SolutionArray solve(PathMatrix input) {

    V = input.getNbVertex();
    path = new int[V];

    /** Set all path to non-visited **/
    boolean[] visited = new boolean[V];
    for (int i = 0; i < V; i++) {
        visited[i] = false;
    }

    Arrays.fill(path, -1);
    graph = input.getMatrix();

    try {
        path[0] = input.getFirstVertex();
        pathCount = 1;

        findPaths(0);

        System.out.println("No solution");
    } catch (Exception e) {

        System.out.println("\nSolution found");
        //input.printMatrix();
        displayAndWrite();
    }

    return solution;

}

/**
 * function to find paths recursively
 */
private void findPaths(int vertex) throws Exception {


    /** solution **/
    if (graph[vertex][0] >= 1 && pathCount == V) {
        throw new Exception();
    }
    /** all vertices selected but last vertex not linked to 0 **/
    if (pathCount == V)
        return;

    for (int v = 0; v < V; v++) {
        /** if connected **/
        if (graph[vertex][v] >= 1) {
            /** add to path **/
            path[pathCount++] = v;

            /** if vertex not already selected solve recursively **/
            if (!isPresent(v))
                findPaths(v);

            /** remove path **/
            path[--pathCount] = -1;

        }

    }

}

/**
 * function to check if path is already selected
 */
private boolean isPresent(int v) {
    for (int i = 0; i < pathCount - 1; i++)
        if (path[i] == v)
            return true;
    return false;
}
private SolutionArray解决方案;
私有int V,路径计数;
私有int[]路径;
私有int[][]图;
/**
*建造师
*/
公营机构({
溶液=新溶液射线();
}
@凌驾
公共解决方案光线解算(路径矩阵输入){
V=input.getNbVertex();
路径=新整数[V];
/**将所有路径设置为“未访问”**/
布尔[]访问=新布尔[V];
对于(int i=0;i=1&&pathCount==V){
抛出新异常();
}
/**已选定所有顶点,但最后一个顶点未链接到0**/
if(路径计数==V)
返回;
对于(int v=0;v=1){
/**添加到路径**/
路径[pathCount++]=v;
/**如果尚未选择顶点,则递归求解**/
如果(!isPresent(v))
findPaths(五);
/**删除路径**/
路径[--pathCount]=-1;
}
}
}
/**
*函数检查是否已选择路径
*/
私有布尔值isPresent(int v){
对于(int i=0;i
我能找到一个第一哈密顿循环。是否有可能对其进行调整以找到图中所有可能的哈密顿圈

输入是一个非对称矩阵(节点之间的一些链接是单向的),一些节点可能有2个或3个到其他节点的链接

多谢各位

编辑:


为了澄清,该算法已经可以找到一个解决方案,但无法找到第二个解决方案,以此类推。从阅读中可以看出,使用bactracking*可以解决这个问题,但我不确定它是否可以添加到我已经拥有的内容中。

目前,您有一个数组来捕获当前正在探索的路径。您的
display和write
方法可能会使用此信息打印解决方案

为了记录所有的解,当你找到哈密顿循环时,你需要一个路径的副本

有点像:

private static final int MAX_SOLUTIONS = 100;
private int[][] solutions = new int[MAX_SOLUTIONS][];
private int solutionCount = 0;

private void addSolution(int[] path) {
    if (solutionCount < MAX_SOLUTIONS)
        solutions[solutionCoun++] = Arrays.copyOf(path, path.length);
}
private static final int MAX_SOLUTIONS=100;
私有int[]solutions=新int[MAX_solutions][];
私有int solutionCount=0;
私有void addSolution(int[]路径){
if(溶液计数<最大溶液)
solutions[solutionCoun++]=Arrays.copyOf(path,path.length);
}
您需要在当前处理异常的递归方法中调用
addSolution


顺便说一句,几乎所有有经验的Java程序员都认为抛出一个表示成功的异常是糟糕的风格。我希望在其他语言中也是如此-异常用于异常:-)

现在,当检测到一个循环时,您会抛出一个异常:

if (graph[vertex][0] >= 1 && pathCount == V) {
    throw new Exception();
}
除了抛出一个异常是错误的,因为它并不是一个真正的异常情况——请看我对这个问题的评论——你所需要做的就是在你发现这个周期没有那么“爆炸性”时采取行动

如果不知道Solutionaray的定义,我就无法利用它给出答案

由于您不知道可以找到多少个周期,请添加
列表
,以收集您的解决方案:

private List<int[]> solutions = new ArrayList<>();
因为这只是从方法返回,而不是抛出异常,所以调用函数的执行将继续检查下一个可能的路径

获取路径的副本很重要,因为否则,您只需添加对用作工作副本的数组的引用,因此它们都将是同一个数组,并且,由于您可能会在之后更新它,因此最后甚至不一定包含有效的解决方案

然后,在main方法中,只需检查此列表是否为非空:

if (!solutions.isEmpty()) {
  System.out.println("\nSolution(s) found");
  displayAndWrite();
}

与其说是对您的问题的评论,不如说是对您的实现的评论:您不应该使用异常来表示已经找到了解决方案。例外是指例外的事物。见第二版第57项。调用此方法有两种结果:void和Exception。你可以很容易地将其设为假或真,或者一个enum没有被发现和发现,这将更容易摸索。这很好,但它没有告诉我如何检测多个解决方案周期。一旦我找到了,该怎么处理them@JulioQc请仔细阅读我的答案并思考控制流程。具体来说,为什么您的代码在找到一个解决方案后会停止,而这可能不会停止?
if (!solutions.isEmpty()) {
  System.out.println("\nSolution(s) found");
  displayAndWrite();
}