欧拉回路

定义

图中经过所有边恰好一次的路径叫欧拉路径.

如果此路径的起点和终点相同,则称其为一条欧拉回路.

有向图欧拉路径

1. 恰好存在 $\mathrm{1}$ 个点出度比入度多 $\mathrm{1}$ (这个点即为起点 $\mathrm{s}$)
2. 恰好存在 $\mathrm{1}$ 个点入度比出度多 $\mathrm{1}$ (这个点即为终点 $\mathrm{t}$)
3. 其余节点出度 $\mathrm{=}$ 入度

找到起点后对于每个点遍历一个没遍历过的边即可.  

开一个 $\mathrm{del[x]}$ 数组表示前 $\mathrm{del[x]}$ 个边已遍历过,然后更新即可.

#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>
#define N  100009 
#define ll long long 
#define pb push_back 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;
vector<int>G[N];
stack<int>se;  
int n , m , del[N], deg[N][2];
void dfs(int x) {
    for(int i = del[x]; i < G[x].size() ; i = del[x]) {
        ++ del[x];       
        dfs(G[x][i]); 
    }
    se.push(x);   
}   
int main() {
    // setIO("input");
    scanf("%d%d", &n, &m); 
    for(int i = 1; i <= m ; ++ i) {
        int x, y; 
        scanf("%d%d", &x, &y); 
        G[x].pb(y);    
        deg[x][1]++; 
        deg[y][0]++;    
    }       
    int flag = 0, s1 = 0, s2 = 0, sta = 1;  
    for(int x = 1; x <= n ; ++ x) {
        if(deg[x][0] != deg[x][1]) 
            ++ flag;      
        // printf("%d %d %d\n", x, deg[x][0], deg[x][1]); 
        if(deg[x][0] - deg[x][1] == 1) s1 = x; 
        if(deg[x][1] - deg[x][0] == 1) s2 = x; 
    }
    // printf("%d\n", flag);  
    if((flag == 0) || ((flag == 2) && s1 && s2)) {
        // 合法
        if(s2) sta = s2;    
        for(int i = 1; i <= n ; ++ i) sort(G[i].begin(), G[i].end());       
        dfs(sta);  
        while(!se.empty()) {
            printf("%d ", se.top()); 
            se.pop();   
        }
    }
    else {
        printf("No"); 
    }
    return 0;
}

  

有向图欧拉回路

1. 所有点出度等于入度

无向图欧拉路径

1. 恰好两个点度数为奇数

2. 其余点度数为偶数

这里面度数为奇数的点就是起点和终点.   

和有向图的求法差不多,不过要开一个 $\mathrm{map}$ 记录一条无向边是否被遍历过.      

若该边已被定向,则不能继续访问了. 

#include <bits/stdc++.h>
#define N  100009 
#define ll long long 
#define pb push_back 
#define mp make_pair
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;
int m , deg[N], del[N];  
stack<int>se;     
vector<int>G[N]; 
map<pair<int, int>, int>vis; 
void dfs(int x) {
    for(int i = del[x]; i < G[x].size() ; i = del[x]) {
        ++ del[x];    
        int v = G[x][i]; 
        if(!vis[mp(x, v)]) continue;   
        vis[mp(x, v)] -- ; 
        vis[mp(v, x)] -- ;  
        dfs(v);    
    }
    se.push(x); 
}
int main() {
    // setIO("input");   
    scanf("%d", &m);  
    int st = N; 
    for(int i = 1; i <= m ; ++ i) {
        int x, y; 
        scanf("%d%d", &x, &y); 
        G[x].pb(y); 
        G[y].pb(x); 
        ++ deg[x], ++ deg[y];   
        st = min(st, min(x, y));    
        vis[mp(x, y)] ++ ; 
        vis[mp(y, x)] ++ ; 
    }
    for(int i = 1; i <= 500; ++ i) {
        sort(G[i].begin(), G[i].end());  
    }
    for(int i = 1; i <= 500; ++ i) {
        if(deg[i] & 1) {
            st = i; 
            break; 
        }
    }   
    dfs(st);
    while(!se.empty()) {
        printf("%d\n", se.top()); 
        se.pop(); 
    } 
    return 0; 
}

  

无向图欧拉回路

1. 所有点度数为偶数  

 

posted @ 2022-02-05 17:00  guangheli  阅读(93)  评论(0)    收藏  举报