JGraphT中SimpleGraph的哈密顿路径与环检测及获取方案咨询
解决JGraphT中非完全图的哈密顿路径/环问题
嘿,刚好对JGraphT里的哈密顿问题有研究,给你几个不用转完全图、也不用自己实现算法的实用方案:
一、找哈密顿环:直接用BacktrackingHamiltonianCycle
这个类完全踩中你的需求——它不需要输入完全图,直接在你的SimpleGraph上通过回溯算法搜索哈密顿环,完全不用额外添加大量冗余边。
用法超级直观,实例化后调用findHamiltonianCycle方法就行,存在环时返回GraphPath对象,不存在则返回null。代码示例:
import org.jgrapht.Graph; import org.jgrapht.alg.tour.BacktrackingHamiltonianCycle; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.SimpleGraph; public class HamiltonianCycleDemo { public static void main(String[] args) { // 初始化你的SimpleGraph Graph<String, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class); graph.addVertex("A"); graph.addVertex("B"); graph.addVertex("C"); graph.addVertex("D"); graph.addEdge("A", "B"); graph.addEdge("B", "C"); graph.addEdge("C", "D"); graph.addEdge("D", "A"); graph.addEdge("A", "C"); // 查找哈密顿环 BacktrackingHamiltonianCycle<String, DefaultEdge> cycleFinder = new BacktrackingHamiltonianCycle<>(); GraphPath<String, DefaultEdge> hamiltonianCycle = cycleFinder.findHamiltonianCycle(graph); if (hamiltonianCycle != null) { System.out.println("找到哈密顿环:" + hamiltonianCycle.getVertexList()); } else { System.out.println("该图不存在哈密顿环"); } } }
需要注意的是,回溯算法的时间复杂度是O(n!),所以这个方法更适合中小规模的图(比如顶点数n < 20),如果是超大图,效率会比较受限。
二、找哈密顿路径:基于虚拟顶点的巧妙转化
JGraphT目前没有直接的非完全图哈密顿路径现成实现,但我们可以基于上面的BacktrackingHamiltonianCycle做个小技巧转化:
- 创建临时图,在原
SimpleGraph基础上添加一个虚拟顶点,让它和所有原有顶点相连 - 查找临时图的哈密顿环——这个环必然会经过虚拟顶点
- 从环中移除虚拟顶点,剩下的顶点序列就是原Graph的哈密顿路径
这种方式只需要添加n条边(n是原顶点数),远少于转完全图需要的边数,完全在可接受范围内。代码示例:
import org.jgrapht.Graph; import org.jgrapht.alg.tour.BacktrackingHamiltonianCycle; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.SimpleGraph; import java.util.List; public class HamiltonianPathDemo { public static void main(String[] args) { // 初始化原SimpleGraph Graph<String, DefaultEdge> originalGraph = new SimpleGraph<>(DefaultEdge.class); originalGraph.addVertex("A"); originalGraph.addVertex("B"); originalGraph.addVertex("C"); originalGraph.addVertex("D"); originalGraph.addEdge("A", "B"); originalGraph.addEdge("B", "C"); originalGraph.addEdge("C", "D"); originalGraph.addEdge("A", "D"); // 创建临时图并添加虚拟顶点 Graph<String, DefaultEdge> tempGraph = new SimpleGraph<>(DefaultEdge.class); String dummyVertex = "DUMMY"; tempGraph.addVertex(dummyVertex); // 复制原顶点和边到临时图 for (String vertex : originalGraph.vertexSet()) { tempGraph.addVertex(vertex); tempGraph.addEdge(dummyVertex, vertex); } tempGraph.addEdgeSet(originalGraph.edgeSet()); // 查找临时图的哈密顿环 BacktrackingHamiltonianCycle<String, DefaultEdge> cycleFinder = new BacktrackingHamiltonianCycle<>(); GraphPath<String, DefaultEdge> tempCycle = cycleFinder.findHamiltonianCycle(tempGraph); if (tempCycle != null) { List<String> pathVertices = tempCycle.getVertexList(); // 移除虚拟顶点,得到原Graph的哈密顿路径 pathVertices.remove(dummyVertex); System.out.println("找到哈密顿路径:" + pathVertices); } else { System.out.println("该图不存在哈密顿路径"); } } }
三、补充:针对特殊图的优化方案
如果你的图满足Chvatal条件(n≥3的图,按顶点度数从小到大排序v₁≤v₂≤…≤vₙ,对于所有k < n/2,要么vₖ的度数>k,要么vₙ₋ₖ的度数≥n−k),可以用ChvatalHamiltonianCycle类,它能高效构造哈密顿环,且不需要完全图。不过这个方法的适用范围有限,只适合满足特定条件的图。
内容的提问来源于stack exchange,提问作者Jens Schauder
相关产品推荐
相关产品推荐

