歐拉回路算法


一.歐拉回路的判定

主要分為兩大類

無向圖歐拉回路判定:

1、歐拉路徑:即可以一筆畫,充要條件是度數為奇數的點的個數為0或2。

2、歐拉回路:歐拉路徑構成一個圈,充要條件是全部是偶點

 

有向圖歐拉回路判定

1、歐拉路徑:起點出度比入度大1,終點入度比出度大1,其他點全部是偶點

2、歐拉回路:每個點出度和入度都相等,且存在一系列環可以覆蓋原圖。

 

題目 hihocoder1176

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 1e5 + 100;
int in[maxn];
int main()
{
    int n, m, x, y;
    cin>>n>>m;
    for(int i = 1; i <= m; i++){
        cin>>x>>y;
        in[x]++;
        in[y]++;
    }
    int t = 0;
    for(int i = 1; i <= n; i++) if(in[i]&1) t++;
    if(t == 0 || t == 2) cout<<"Full"; else cout<<"Part";
}

 

二、歐拉路徑的求法

使用Fleury算法求

原理,先找到起點(根據判定)

然后由起點找到dfs出一條路徑L1,那么L1的終點必定是判定里說的終點,於是把L1上所有的邊刪掉,我們再進行增廣

對於L1上每一個點,如果它仍然可以連向其他點,那么就可以繼續走,以歐拉回路的方式再次回到這個點

在這個過程中可能會再次形成L1'回路,然后對L1'回路繼續這樣做,遞歸下去即可

最后按照棧的方式輸出就可以了,利用dfs的性質可以很簡單的做到

hihocoder 1181

#include <iostream>
#include <cstdio>
#include <vector>
#define fi first
#define se second
using namespace std;
const int maxn = 1e5 + 100;
typedef pair<int, int> PII;
vector<int> G[maxn], V;
vector<PII> edges;
int f[maxn];
void dfs(int x){
    for(auto i : G[x]){
        auto e = edges[i];
        if(f[i]) continue;
        f[i] =  1;
        dfs(e.fi == x ? e.se : e.fi);
    }
    cout<<x<<" ";
}
int main()
{
    int n, m, x, y;
    cin>>n>>m;
    for(int i = 1; i <= m; i++){
        cin>>x>>y;
        edges.push_back({x, y});
        G[x].push_back(i-1);
        G[y].push_back(i-1);
    }
    for(int i = 1; i <= n; i++) if(G[i].size() & 1) V.push_back(i);
    int s = V.size() ? V[0] : 1;
    dfs(s);
    return 0;
}

 

三、簡單應用

hihocoder 1182

求一個長度為2^n的字符串,使他的每n位恰好構成0~2^n-1

比如說n=3時, 答案為 00010111

即000,001,010,101,011,111,110,100

 

建圖,比如說001就建(00)->(01), 011建(01)->(11),然后走完所有的邊,實際上就構造了一個歐拉回路

 

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#define fi first
#define se second
using namespace std;
const int maxn = (1<<15) + 100;
typedef pair<int, int> PII;
vector<int> G[maxn], ans;
vector<PII> edges;
int f[maxn];
int n;
void dfs(int x){
    for(auto i : G[x]){
        if(f[i]) continue;
        f[i] = 1;
        dfs(edges[i].se);
    }
    ans.push_back(x);
}

int main()
{
    cin>>n;
    if(n == 1) { cout<<"01"<<endl; return 0; }
    for(int i = 0; i < (1<<n); i++){
        int y = i&((1<<(n-1))-1), x = i>>1;
        edges.push_back({x, y});
        G[x].push_back(edges.size()-1);
    }
    dfs(0);
    reverse(ans.begin(), ans.end());
    for(int i = 1<<(n-1); i >= 1; i >>= 1){
        if(i&ans[1]) cout<<"1";
        else cout<<"0";
    }
    for(int i = 2; i < ans.size()-n+1; i++){
        if(ans[i]&1) cout<<"1";
        else cout<<"0";
    }
}

 

00010111


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM