算法图论学习-欧拉路判断(有向图)

312 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

欧拉路

欧拉路指的是在途中存在一条路线可以重一点出发不重复的经过所有路径

欧拉回路

欧拉回路就是可以可以回到起点的欧拉路我们平常的一笔画问题其实就是欧拉路问题

如何用算法去判断欧拉路并输出一条路径

当我们去判断这个图是不是欧拉路的时候我们有三种可能性

  1. 简单的欧拉路
  2. 欧拉回路
  3. 非欧拉路
    如果这个图是一个简单的欧拉路时那么这个路径起点和终点的路径的出度和入度时不相等的如果这个点是起点我们就可以发现它的出度等于它的入度加一并且整条路径只有两个点的出度和入度不等(起点和终点)
    当这个图是一个欧拉回路是我们可以发现它图中所有点的出度都等于入度
int x = 0, y = 0, z = 0;// x 表示起点 y 表示有多少出度等于入度加一的点 z表示有多少出度不等于入度的点
     for(int i = 1; i <= n; i++) {
        if(cd[i] == rd[i] + 1) {
            x = i, y ++;
        }
        if(cd[i] != rd[i]) z++;
     }
     if(!(!z || (y == 1 && z == 2))) { // 判断是否存在欧拉回路
         cout << "No" << endl;
         return;

所有当我们去判断这个图是不是一个欧拉回路时我们就有两种判断方法,这样我们就可以简单的去判断下这个图是不是一个欧拉路。如果我们想获得一个欧拉路径我们还需要进行一个dfs的操作,先放代码吧有时间再配图解释

vector<int> e[N];
int n , m;
int rd[N], cd[N], que[N], tot, f[N]; // f[x] 防止重复使用

void dfs(int x) {
    int len = e[x].size();
    while(f[x] < len) {
        int y = e[x][f[x]];
        f[x] ++;
        dfs(y);
        que[++tot] = y;
    }
}

// 有向图判断欧拉回路
void Euler() {
     int x = 0, y = 0, z = 0;// x 表示起点
     for(int i = 1; i <= n; i++) {
        if(cd[i] == rd[i] + 1) {
            x = i, y ++;
        }
        if(cd[i] != rd[i]) z++;
     }
     if(!(!z || (y == 1 && z == 2))) { // 判断是否存在欧拉回路
         cout << "No" << endl;
         return;
     }
     if(!x) for(int i = 1; i <= n; i++) if(rd[i]) x = i;
     dfs(x);que[++tot] = x;
 

更新

因为我们通过之前的操作发现这个有向图中是肯定存在欧拉路的所有我现在需要找出这个欧拉路

image.png

如图所示这也是一种欧拉路我们会发现这其实就是走环所有我们用dfs去处理我们的f数组是表示这个点几条路径都走过了不能再走