基本概念
- 欧拉通路:一条经过图上所有边的路径(每条边只经过一次)
- 欧拉回路:当欧拉通路为回路时,称为欧拉回路
对于无向图
- 当无向连通图中不存在奇点时,该图存在欧拉回路
- 当无向连通图中存在奇点且只存在两个奇点时,该图必定存在欧拉通路
对于有向图
- 若图连通且每个点的出度与入度相等,则存在欧拉回路
- 若图连通、有且仅有两个点出度与入度不相等,且两个点入度与出度只差为1。则通路的起点一定是出度多1的点,终点一定是入度比出度多1的点
Hierholzer算法
- 给定欧拉通路/回路的起点
- 开始递归函数dfs(u)
循环寻找与u相连的边(u,v)
删除(u,v)
删除(v,u)//若为有向图则不需要这一步
dfs(v)
将u插入答案栈中 - 出栈,输出结果。
/**
* 欧拉通路和欧拉回路
* @author 1
*
*/
public class Hierholzer {
static class Node{
int v,next,use=0;
Node(int v,int next){
this.v = v;
this.next = next;
}
}
static Node[] edges = new Node[10001];
static int[] heads = new int[10001];
static int cnt;
static void add(int u,int v){
edges[cnt] = new Hierholzer.Node(v, heads[u]);
heads[u] = cnt++;
}
static Stack<Integer> stack = new Stack<Integer>();
static void dfs(int u){
for(int i=heads[u];i!=-1;i=edges[i].next){
int v = edges[i].v;
if(edges[i].use==1) continue;
//edges[i^1].use = 1; //求有向图时不需要这一步
edges[i].use = 1;
dfs(v);
}
stack.push(u);
}
public static void main(String[] args) {
Arrays.fill(heads, -1);
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
for(int i=1;i<=m;i++){
int u,v;
u = in.nextInt(); v = in.nextInt();
add(u,v);
//add(v,u); //无向图
}
dfs(1);
while(!stack.isEmpty()){
System.out.println(stack.pop());
}
}
}