• 浅谈欧拉图(欧拉路径)


    定义

    通过图中所有边恰好一次的通路称为欧拉通路。

    通过图中所有边恰好一次的回路称为欧拉回路

    具有欧拉回路的无向图或有向图称为欧拉图。

    具有欧拉通路但不具有欧拉回路的无向图或有向图称为半欧拉图。

    非形式化地讲,欧拉图就是从任意一个点开始都可以一笔画完整个图,半欧拉图必须从某个点开始才能一笔画完整个图。

    性质

    欧拉图中所有顶点的度数都是偶数。

    判别法

    对于无向图G,G是欧拉图当且仅当  是连通的且没有奇度顶点。

    对于无向图G,G是半欧拉图当且仅当G是连通的且G中恰有0个或2个奇度顶点。

    对于有向图G,G是欧拉图当且仅当G的所有顶点属于同一个强连通分量且每个顶点的入度和出度相同。

    对于有向图G,G是半欧拉图当且仅当

    • 如果将G中的所有有向边退化为无向边时,那么G的所有顶点属于同一个连通分量。
    • 最多只有一个顶点的出度与入度差为1。
    • 最多只有一个顶点的入度与出度差为1。
    • 所有其他顶点的入度和出度相同。

    上述有向图G且G为半欧拉图可以简单说为满足以下两个性质其中之一即可

    1.有向图G中所有顶点的入度与出度相等

    2.有向图G中有且只有一个顶点的入度为其出度+1(该点为终点),并且有且只有一个顶点的出度为其入度+1(该点为起点),其他点的入度与出度相等

    求解欧拉路径可以使用Fleury算法(避桥法)时间复杂度为O(m^{2}),可用性不大

    一般求解欧拉路径使用Hierholzer算法(逐步插入回路法),不求字典序最小的欧拉路径时的时间复杂度为O(n+m),求字典序最小的欧拉路径时,需要对每个点所能到达的点进行从小到大排序,因此时间复杂度为O(n+mlogm)

    【模板】欧拉路径 - 洛谷

    求解字典序最小的欧拉路径

    AC代码:

    1. #include
    2. using namespace std;
    3. using LL = long long;
    4. int main() {
    5. ios::sync_with_stdio(false);
    6. cin.tie(nullptr);
    7. int n, m;
    8. cin >> n >> m;
    9. vectorint>> G(n + 1);
    10. vector<int> in(n + 1), out(n + 1);
    11. for (int i = 0; i < m; i++) {
    12. int u, v;
    13. cin >> u >> v;
    14. G[u].push_back(v);
    15. out[u]++;
    16. in[v]++;
    17. }
    18. int st = -1, end = -1, zz;
    19. bool ok = true;
    20. for (int i = 1; i <= n; i++) {
    21. if (in[i] == out[i]) {
    22. zz = in[i];
    23. continue;
    24. }
    25. else {
    26. if (in[i] == out[i] + 1 and end == -1) {
    27. end = i;
    28. }
    29. else if (out[i] == in[i] + 1 and st == -1) {
    30. st = i;
    31. }
    32. else {
    33. ok = false;
    34. break;
    35. }
    36. }
    37. }
    38. if (!ok) {
    39. cout << "No\n";
    40. exit(0);
    41. }
    42. for (int i = 1; i <= n; i++) {
    43. sort(G[i].begin(), G[i].end());
    44. }
    45. if (st == -1) {
    46. st = 1;
    47. }
    48. stack<int> sta;
    49. vector<int> cur(n + 1);
    50. function<void(int)> dfs = [&](int x) {
    51. int len = G[x].size();
    52. for (int i = cur[x]; i < len; i = cur[x]) {
    53. cur[x] = i + 1;
    54. dfs(G[x][i]);
    55. }
    56. sta.push(x);
    57. };
    58. dfs(st);
    59. while (!sta.empty()) {
    60. cout << sta.top() << ' ';
    61. sta.pop();
    62. }
    63. return 0;
    64. }

  • 相关阅读:
    CAN转4G远程透传记录云网关为工程机械赋能
    Leetcode 687. 最长同值路径
    【FPGA】通俗理解从VGA显示到HDMI显示
    C语言中,基本数据类型介绍
    【Jprofile 11.0 安装】
    安防监控/视频存储/视频汇聚平台EasyCVR接入海康Ehome车载设备出现收流超时的原因排查
    关于2023年下半年计算机技术与软件专业技术资格(水平)考试报名工作有关事项的通知
    软件测试的前景怎么样?自学软件测试要怎么学?
    vue3上传文件组件方法封装
    【你也能从零基础学会网站开发】Web建站之javascript入门篇 JavaScript事件处理
  • 原文地址:https://blog.csdn.net/eyuhaobanga/article/details/126550436