问题的引出
- ➢柯尼斯堡七桥问题( Seven Bridges of Konigsberg )是图论中的著名问题。这个问题是基于一个现实生活中的事例:当时东普鲁士柯尼斯堡(今日俄罗斯加里宁格勒)市区跨普列戈利亚河两岸,河中心有两个小岛。小岛与河的两岸有七条桥连接。在所有桥都只能走一遍的前提下,如何才能把这个地方所有的桥都走遍?
- ➢能否从无向图中的一个结点出发走出一条道路,每条边恰好经过一次,这样的路线称为欧拉道路(一笔画 )。
基本定义和规律
- ➢如果一个无向图是连通的,且最多只有两个奇点(度数为奇数),则一定存在欧拉道路
- ➢如果有两个奇点,它们必须是起点和终点
- ➢如果奇点不存在,可以从任意点出发,最终一定会回到该点 ,称为欧拉回路
- ➢对于有向图,欧拉道路存在的充要条件是:最多只能有两个点的入度不等于出度,而且必须是其中一一个点的出度恰好比入度大1 (起点) ,另一个的入度比出度大1 (终点)
实战演练:
打印出下图的欧拉道路的走法
解题思路:
用邻接矩阵表示图,由于要形成欧拉道路,所以应该从度数为奇数的节点出发;开始进行深搜,在深搜的过程中做标记哪些边走过;可以另用一个相同的邻接矩阵做标记,也可以对原来的邻接矩阵进行修改。
代码如下:
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class 欧拉道路 {
//图的邻接矩阵
private static int[][] graph = {
{0,1,2,1},
{1,0,0,0},
{2,0,0,1},
{1,0,1,0},
};
private static int n = 4; //节点数
private static List<String> l = new ArrayList<String>();
//因为深搜时是先存储后面的路径,所以用栈进行存储
private static Stack<String> path = new Stack<String>();
public static void main(String[] args) {
//从节点数为奇数的开始进行深搜,C的度数为3,所以从C节点开始深搜
dfs(2);
while(!path.isEmpty()){
System.out.println(path.pop());
}
}
private static void dfs(int i) {
//寻找相邻的节点,且边没有使用过
for(int j=0; j<n; j++){
if(graph[i][j]>0){ //右边且没有使用过
//减去使用过的边
graph[i][j]--;
graph[j][i]--;
dfs(j);
//添加走过的路径必须放到深搜后,当深搜到终点时,反向的保存路径。
//如果在深搜前添加路径,可能会将错误的路径给添加进去,
//因为当走到一个只有一条边的节点时,会回溯
path.push((char)('A'+i) +"->" + (char)('A'+j));
}
}
}
}