图 欧拉回路

欧拉道路:即一笔画,从图的一个结点出发走出一条道路,每条边恰好经过一次
欧拉回路:从任意点出发,最终回到该点的欧拉道路
1.前提:忽略边的方向后,图是连通的【dfs、bfs、并查集】
2.条件:
有向图:最多只有两个点的入度不等于出度,且相差的绝对值是1
无向图:最多只有两个点的度是奇数
3.若有特殊点,则特殊的点为起点,若无任意点都可为起点
寻找路径方法:DFS构造

一般的版本

void euler(int u) {
    for (int v = 0; v < n; ++v)
        if (G[u][v] && !vis[u][v]) {
            vis[u][v] = vis[v][u] = 1;
            euler(v);
            path.push_back(v);
        }
}

递归版本(图很大,不能用邻接矩阵)

#include<iostream>
#include<vector>
using namespace std;
const int maxn = 10005;
const int maxm = 100005;
struct Edge{
    int M,vis;//M是u+v
    Edge(int a = 0,int c = 0) : M(a), vis(c) {};
};
vector<Edge> Edges;
vector<int> G[maxn];//G[k]代表k结点相连的路径编号(Edges[]编号)
vector<int> path;
int n, m,a,b;
void euler(int u) {
    for (int i=0;i<G[u].size();++i)
        if (!Edges[G[u][i]].vis) {
            int v = Edges[G[u][i]].M - u;
            Edges[G[u][i]].vis = 1;
            euler(v);
            path.push_back(v);
        }
}

迭代版本(栈溢出的情况下使用)

#include<iostream>
#include<vector>
using namespace std;
const int maxn = 10005;
const int maxm = 100005;
struct Edge{
    int M,vis;
    Edge(int a = 0,int c = 0) : M(a), vis(c) {};
};
vector<Edge> Edges;
vector<int> G[maxn];//G[k]代表k结点相连的路径编号(Edges[]编号)
vector<int> path;
int n, m,a,b,i;
Edge x;
vector<Edge> sta;//代表:M=u,vis=i
void euler(int u) {
    i = 0;
    while (1) {
        for (; i<G[u].size(); ++i)
            if (!Edges[G[u][i]].vis) {
                int v = Edges[G[u][i]].M - u;
                Edges[G[u][i]].vis = 1;
                sta.push_back(Edge(u, i));
                u = v; i = 0;
                break;
            }
        if (!i) continue;//只有break下来的i是等于0的,其他都是>0,不存在不连通图的欧拉路径
        if (sta.empty()) break;
        x = sta.back(); sta.pop_back();
        u = x.M, i = x.vis;
        path.push_back(Edges[G[u][i++]].M - u);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值