There are such problems in graph theory, which involve Euler diagrams, Euler paths (one-stroke problems), and Euler circuits. This article gives its (not rigorous) definition, some conclusions, and finally the Hierholzer algorithm and corresponding examples and answers.
(Not rigorous) definition
For a 连通的
graph G, there are
- Euler path : a path that can traverse all edges without repeating it. This property is like drawing all the edges in one stroke without repeating it, so some of
欧拉路径
the problems involved are called一笔画问题
. - Euler circuit : a path that can traverse all edges without repeating it and return to the starting point. It can be seen that
欧拉回路
too欧拉路径
. - Semi-Euler diagram : A diagram, which exists in the diagram
欧拉路径
. - Euler Diagram : A diagram, which exists in the diagram
欧拉回路
. It can be seen that欧拉图
too半欧拉图
.
Figure and the conclusion of Euler path and Euler circuit
The connected condition 无向图
is the (semi) Euler diagram :
- If the degree of all vertices is even, it can be found from any vertex
欧拉回路
. The opposite is also true, that is, if a starting point can be found from any vertex欧拉回路
, the degree of all vertices is even. - If there are and only two vertices with odd degrees, they can only be found
欧拉路径
(the path starts from either vertex of the two points and ends at the other vertex). The opposite is also true.
The connected condition 有向图
is the (semi) Euler diagram :
- If the in-degree of all vertices is equal to the out-degree, then one can find the starting point from any vertex
欧拉回路
. The opposite is also true. - If there are and only two vertices, the in-degree is not equal to the out-degree, and the in-degree of one of the vertices is greater than the out-degree by 1, which is recorded as V 1 V_1V1, The in-degree of the other vertex is 1 less than the out-degree, denoted as V 2 V_2V2, You can only find
欧拉路径
(the path from the vertex V 2 V_2V2Departure to vertex V 1 V_1V1End). The opposite is also true.
Connected 混合图
is the condition of the (semi) Euler graph : ( 混合图
refers to a graph with both directed and undirected edges.)
- Find a strategy to orient each undirected edge so that the in-degree of each vertex is equal to the out-degree, so that it can be converted into a directed graph. (
这个有待考究
)
Hierholzer algorithm
Brief description of the problem : Given a (semi) Euler diagram, find the Euler path.
Hierholzer algorithm idea : when a given graph must have 欧拉路径(回路
), starting from a 合理的
starting point (what will be said later is reasonable), depth-first traversal of the entire graph, traversed vertices must not be traversed again, until the first encountered a 没有可遍历的邻居
vertex, this vertex point is the end of a strip Euler path to the top "delete" (without actually deleted, accessed by marking edge can no longer access it), the next encounter 没有可遍历的邻居
vertex , It must be the penultimate vertex of this Euler path, and then "delete" this vertex and traverse again, and so on, until all 没有可遍历的邻居
the vertices are found, we have found all the vertices on this Euler path. :
Question 1 : Some people may wonder why the Hierholzer algorithm must be able to get Euler path? Why is every 没有可遍历的邻居
vertex encountered is an end point on Euler's path? 下面以有向图作为说明,无向图同理。
This actually involves the out-degree and in-degree of a vertex.
If the traversal starts from a certain vertex, the traversed edge cannot be traversed until there is no edge to traverse. When another out-degree equals to the in-degree vertex VVWhen V , it is impossible to stay atVVV , becauseVVV out degree is equal to in degree.入
How many timesyou enter, there must be a corresponding out side for you出
to go.
Therefore, the first没有可遍历的邻居
vertexencountered isonly two types, one is that its in-degree is one greater than its out-degree, and the other is its in-degree and out-degree are equal, but it is the starting point (that is, it is both a starting point and a Is the end, spare a lap). According to some of the conclusions mentioned above (the conclusions of thegraph and Euler path, Euler circuit), these two points are the end points on a certain Euler path, so when we encounter没有可遍历的邻居
the vertices, although you can rest assured and bold This vertex is recorded because it must be the end of Euler's path.
Question 2: Some people may wonder why the second没有可遍历的邻居
vertexencountered is the second tolast point of Euler's path? We can imagine that after I没有可遍历的邻居
"delete"the firstvertex and the corresponding edge (actually, it doesn't need to be deleted, just mark it has been visited), the out degree and in degree of its adjacent vertices will happen Change, draw on the draft paper and you will find that the vertices around it either become vertices with out-degree equal to in-degree, or vertices with in-degree greater than out-degree by 1, and they all conform to the end point of Euler’s path. Condition, and because we are depth-first traversal recursively, after recursively returning to the previous layer, it must be among these adjacent vertices, so the second没有可遍历的邻居
vertexencountered at this timemust be the second to last Euler path point.
Hierholzer algorithm process :
- Choose one
合理的点
as the starting point and traverse all adjacent edges. (I will say what is合理的点
) - Depth first search, visit adjacent vertices. The sides that will pass can no longer be visited.
- If the current vertex has no adjacent edges, the vertex is placed at the end of the array.
- Finally, the array is output in reverse order, which is the Euler circuit starting from the starting point.
Hierholzer algorithm function : I personally feel that it Hierholzer 算法
is proof that when a given graph must have 欧拉路径(回路
), according to the Hierholzer 算法
brainless depth-first search, you will definitely get 欧拉路径(回路)
the reverse order. As for whether you get it 欧拉路径
or not 欧拉环路
, it depends on whether your picture is 欧拉图
still 半欧拉图
. If the picture 欧拉图
is 欧拉环路
, what you get is , if the picture is 半欧拉图
, what you get is yes 欧拉路径
. Why can Hierholzer algorithm get Euler path? What is its principle? Please look here .
Note: If the picture is not 欧拉图
or not 半欧拉图
, Hierholzer 算法
the result obtained by using it must be wrong. Therefore, before adopting it rashly Hierholzer 算法
, we need to judge whether the graph is in the end according to the conclusions of the graph and Euler path and Euler circuit mentioned above . (半)欧拉图
If it is , then we can use this algorithm to find it 欧拉路径(回路)
.
What is the 合理的
starting point : The above mentioned choice 合理的点
as the starting point, so what is the point 合理的
? Here we need to review the relationship between the previously mentioned graph and Euler path and Euler circuit . Take the undirected graph as an example (the same is true for directed graphs):
- When the picture is an Euler diagram, you can find a starting point from any point
欧拉回路
. At this time, starting from any point, you can find the Euler circuit, so any point is合理的
; - When the graph is a semi-Eulerian graph, there are only two vertices with odd degrees, and they can only be found
欧拉路径
(the path starts at any one of these two points and ends at the other point). As soon as we set off, we can find Euler's path, so only these two points are合理的
.
Example : In order to master the Hierholzer algorithm, here is an example [leetcode] 332. The
answer to the example question of rearranging the itinerary (C++) :
// 思路:
// Hierholzer算法。个人觉得Hierholzer算法就是证明了一点:当存在欧拉路径时,从合理的起始点无脑dfs遍历,得到的路径一定是欧拉路径。
// 因为题目规定了一定有欧拉路径,并且起点一定是JFK(所以这个起始点一定是合理的),所以根据Hierholzer算法,可以无脑dfs。
class Solution {
public:
// 这里用map,内部自动按照string升序排列了,所以先找到的一定是自然排序最小的路径
typedef unordered_map<string, map<string, int>> adjacent;
vector<string> min_path;
bool dfs(adjacent &adj, string airport){
// 无脑dfs遍历邻居,同时遍历过的边标记已遍历
for(auto &[next, number] : adj[airport]){
if(0 >= number)
continue;
--number;
dfs(adj, next);
}
// 终点是没有相邻边的点
// 当删除终点后,终点前的点也没有相邻边了,变成新的终点
// 运行到这里,当前airport一定没有可遍历的相邻边了,则它是此时的终点
min_path.push_back(airport);
return true;
}
vector<string> findItinerary(vector<vector<string>>& tickets) {
// 初始化邻接表,因为存在多张相同机票的情况,所以邻接表中还记录了从from到to的机票数
adjacent adj;
for(auto & t : tickets){
if(adj.find(t[0]) == adj.end())
adj[t[0]] = map<string, int>();
if(adj[t[0]].find(t[1]) == adj[t[0]].end())
adj[t[0]][t[1]] = 0;
adj[t[0]][t[1]]++;
}
// Hierholzer算法
dfs(adj, "JFK");
// Hierholzer算法得到结果为终点到起点的路径,需要反转才是题目所要求的结果
std::reverse(min_path.begin(), min_path.end());
return min_path;
}
};
Related/reference links
"Graph theory" entry and Hierholzer algorithm
Euler / path [summary]
no Euler paths, loops template (Hierholzer algorithm) to map