zoukankan      html  css  js  c++  java
  • 欧拉回路心得

    对于欧拉回路为什么一定要用栈,偶进行了一下小小的探究(感谢崔学长的数据)。

    样例如图所示:

     不用栈,直接输出会怎样呢?

    void euler(int u){
        for(int v=1; v<=n; v++){
            if(G[u][v]){
                G[u][v]--;
                G[v][u]--;
                printf("%d %d\n", u, v);
                euler(v);
            }
        }
    }

    输出结果如下:

    一开始输出路径会是1->2->3->4->1,搜完这些,会从3开始继续搜索并输出,3->5->6->7->3。很明显,这是错误的。、

    那么用栈呢?

    void euler(int u){
        for(int v=1; v<=n; v++){
            if(G[u][v]){
                G[u][v]--;
                G[v][u]--;
                euler(v);
                S.push(node(u, v));
            }
        }
    }

     在main函数里添加:

    while(!S.empty()){
        node e = S.top(); S.pop();
        printf("%d %d\n", e.x, e.y);
    }

    结果如下:

    假设当前走到了3结点,那么下一个应当是4,然后是1,接着的操作是将4->1,3->4入栈,进行完这些操作,会继续搜索3->5->6->7->3,接着把7->3, 6->7, 5->6, 3->5,2->3, 1->2入栈.

    依次将这些边弹出会如何?如上图结果显示。

    懂了这些,便可将上面代码修改下

    void euler(int u){
        for(int v=1; v<=n; v++){
            if(G[u][v]){
                G[u][v]--;
                G[v][u]--;
                euler(v);
                printf("%d %d\n", v, u)
            }
        }
    }

    测试样例:

    7 8
    1 2
    2 3
    3 4
    4 1
    3 5
    5 6
    6 7
    7 3

    下面给出完全的用栈保存路径的代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <stack>
    using namespace std;
    
    const int maxn = 50+20;
    
    int G[maxn][maxn], n;
    
    struct node{
        int x, y;
        node(int x, int y):x(x), y(y) {}
    };
    
    stack<node> S;
    
    void euler(int u){
        for(int v=1; v<=n; v++){
            if(G[u][v]){
                G[u][v]--;
                G[v][u]--;
                euler(v);
                S.push(node(u, v));
            }
        }
    }
    
    int main(){
        int m;
        memset(G, 0, sizeof(G));
        scanf("%d%d", &n, &m);
        for(int i=0; i<m; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            G[u][v] = G[v][u] = 1;
        }
    
        euler(1);
    
        while(!S.empty()){
            node e = S.top(); S.pop();
            printf("%d %d\n", e.x, e.y);
        }
    
        return 0;
    }
  • 相关阅读:
    linux下利用elk+redis 搭建日志分析平台教程
    C# 短信发送 邮件发送
    面向对象编程思想-装饰模式
    面向对象编程思想-桥接模式
    面向对象编程思想-适配器模式
    面向对象编程思想-原型模式
    面向对象编程思想-建造者模式
    面向对象编程思想-抽象工厂模式
    面向对象编程思想-工厂方法模式
    面向对象编程思想-简单工厂模式
  • 原文地址:https://www.cnblogs.com/tanhehe/p/3095952.html
Copyright © 2011-2022 走看看