非常牛 H 开头的算法
考前发现欧拉回路不会。
然后寻求多方大佬,最后比较深刻地理解了一个叫 Hierholzer 的算法。
这个算法暴力写法是:
-
先找一条欧拉路径,然后把这个路径上的点删了。
-
再看看这个链上的点能不能再被换成环,能的话就把这个点换成新找的路径,这步用链表插入,这个过程是递归的。
复杂度很牛逼,是 \(O(n + m)\) 的。
void dfs(int x) {
//找环
}
void h_kai_tou_de_suan_fa(int x) {
dfs(x);
//设 circle 为找到的环
for(int i = 0; i < (int)circle.size() - 1; i++) del_edge(circle[i], circle[i - 1]);
for(auto y : circle) {
h_kai_tou_de_suan_fa(y);
// 在 circle 中插入新找到的环
}
}
但是一看就是巨大难写的东西。考虑有没有优美的写法。
注意到没必要把回路显式建出来。
回溯的时候已经遍历了整条回路,所以回溯的时候去找环就好了。
这就是我们平常见到的欧拉回路为什么要遍历完出边再把当前点入栈的原因。
void dfs(int x){
for(int i = head[x]; i; i = head[x]){
head[x] = e[i].nxt;
dfs(e[i].to);
}
ss.push(x);
}
拜谢 Alex_Wei。
参考文献: