主要參考大佬博客:https://blog.csdn.net/u011815404/article/details/86590498
歐拉圖
歐拉圖是在大家小學時學奧數都學習過的一個類型的題,無論你學得好不好,你都聽過它的另外一個名字:一筆畫問題;
一,首先來定義一下:
1.歐拉回路:圖G的一個回路,如果恰通過圖G的每一條邊,則該回路稱為歐拉回路,具有歐拉回路的圖稱為歐拉圖。歐拉圖就是從圖上的一點出發,經過所有邊且只能經過一次,最終回到起點的路徑。
2.歐拉通路:即可以不回到起點,但是必須經過每一條邊,且只能一次。也叫"一筆畫"問題。
3.基圖:基圖是針對有向圖的說法,是忽略有向圖的方向得到的無向圖。
4.歐拉圖:存在歐拉回路的圖。
歐拉回路一定要首尾相連,,通路不一定。
二.性質與定理
先說說有向圖和無向圖,顯而易見,有向圖就是有向的圖,而無向圖反之亦然。
呃,,此處及以下全轉載至大佬博客:https://blog.csdn.net/qq_35649707/article/details/75578102
性質與定理
定理1
無向圖G為歐拉圖,當且僅當G為連通圖且所有頂點的度為偶數。
證明: 必要性
設圖G的一條歐拉回路為C。由於C經過圖G的每一條邊,而圖G沒 有孤立點,所以C也經過圖G的每一個頂點,G為連通圖成立。而對於圖G的任意一個頂點 v,經過C時都是從一條邊進入,從另一條邊離開,因此v經過C的關聯邊的次數為偶數。又由於C不重復地經過了圖G的每一條邊,因此 的度為偶數。
充分性
假設圖G中不存在回路,而G是連通圖,故 一定是G樹,那么有|E|=|V|−1 |E|=|V|−1|E|=|V|-1由於圖G所有頂點的度為偶數而且不含孤立點,那么圖G的每一個頂點的度至少為2。
推論1
無向圖G為半歐拉圖,當且僅當G為連通圖且除了兩個頂點的度為奇數之外, 其它所有頂點的度為偶數。
證明:將兩個度為奇數的頂點連接,由定理一得該圖為歐拉圖,故去掉環上一邊為半歐拉圖。
定理2
有向圖G為歐拉圖,當且僅當G的基圖連通,且所有頂點的入度等於出度。
推論2
有向圖G為半歐拉圖,當且僅當G的基圖連通,且存在頂點u的入度比出度大1 、v的入度比出度小 1,其它所有頂點的入度等於出度。證明同定理1相似。
性質1
設C是歐拉圖G中的一個簡單回路,將C中的邊從圖G中刪去得到一個新的圖G ′ ′^{'},則 G ′ ′^{'}的每一個極大連通子圖都有一條歐拉回路。
證明 若G為無向圖,則圖G ′ ′^{'}的各頂點的度為偶數;若G為有向圖,則圖 G ′ ′^{'}的各頂點的入度等於出度。
性質2
設 C1、C2是圖G的兩個沒有公共邊,但有至少一個公共頂點的簡單回路,我們可以將它們合並成一個新的簡單回路 。
三.如何判定(是不是歐拉回路/圖)
以下全是我個人理解,完全依據於小奧的學習經驗,不一定全對,有錯請指出。
我說的盡量簡單一點:
首先每一個點都有它的度:即與它相連的邊的個數
我們把奇度的點稱為奇點,反之偶點
根據奧數知識一句話則可以判斷無向圖是否是歐拉圖:有0或2個奇點
但是對於有向圖判斷則復雜一些:每條邊只經過一次而且每個點也只過一次
四。如何實現判定
下面用一道模板題來簡述一下吧。附:歐拉樹的題往往無法判斷是圖論題
見下:
題目描述
給定n個各不相同的無序字母對(區分大小寫,無序即字母對中的兩個字母可以位置顛倒)。請構造一個有n+1個字母的字符串使得每個字母對都在這個字符串中出現。
輸入輸出格式
輸入格式:
第一行輸入一個正整數n。
以下n行每行兩個字母,表示這兩個字母需要相鄰。
輸出格式:
輸出滿足要求的字符串。
如果沒有滿足要求的字符串,請輸出“No Solution”。
如果有多種方案,請輸出前面的字母的ASCII編碼盡可能小的(字典序最小)的方案
輸入樣例#1: 輸出樣例#1:
4 XaZtX aZ tZ Xt aX
是不是很迷?
但是附上代碼你就會懂了。。。。
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; int a[500][500]; int du[200]; char lu[500]; void Find(int now) { for(int i = 'A';i <= 'z';++ i){//字典序從小開始找 if(a[now][i]){ a[now][i] = 0; a[i][now] = 0; Find(i); } } lu[++k] = now;//題目要求記錄的路徑 } int main() { int n; cin>>n; char x,y; for(int i = 1;i <= n;++ i) { cin >> x >> y; a[x][y] = 1; a[y][x] = 1; du[x] ++;//此處du數組記錄了每個點的度數 du[y] ++; } for(int i = 'z';i >= 'A';-- i) { if(du[i] % 2==1) start = i,m ++;//m記錄圖中奇數度數點的個數,同時將起點start定為此點 } if(m != 0&&m != 2) {//由歐拉圖的性質可得,如果一個圖奇數度數點個數不為0或2則不存在歐拉路徑 cout << "No Solution"; return 0; } if(m == 0) {//當圖中所有點為偶數度數時,圖中存在歐拉回路,只需要找到字典序最小的點作起點start for(int i = 'A';i <= 'z';++ i) if(du[i]) { start = i; break; } Find(start); } int str=strlen(lu); for(int j=1;j<=str;j++) cout<<lu[j]; cout<<endl; return 0; }
好了,歐拉圖就掌握到模板題吧,,對我而言
如果大佬們想刷題
請見:
模板題: poj:1041 john’s trip
http://poj.org/problem?id=1041
(無向圖歐拉回路&路徑輸出,模板題,很經典。)
hdu:3018 ant trip
http://acm.hdu.edu.cn/showproblem.php?pid=3018
(並查集:歐拉回路的問題)
一般難度: POJ:1386 Play on Words
http://poj.org/problem?id=1386
(判定有向圖圖歐拉路徑是否存在)
POJ 1300 Door Man
http://poj.org/problem?id=1300
(無向圖歐拉通路和回路的判定+並查集)
究極難度:
大視野oj:太鼓達人
https://www.lydsy.com/JudgeOnline/problem.php?id=3033
這道題是無意中翻到的,完全沒看出來是歐拉圖。需要強大的數學功底才能進行轉化(要用歐拉回路判定+dfs+回溯做)。
這里選了一個題解(思路講的較為清晰,有圖解)
太鼓達人題解
https://blog.csdn.net/Clove_unique/article/details/70160122
uva:10735
是道紫題,此處給的是洛谷傳送門
https://www.luogu.org/problemnew/show/P3372
洛谷題解挺詳細,大家可以看看。
poj:1637 Sightseeing tour
http://poj.org/problem?id=1637
一道好題,網絡流加混合歐拉圖(大佬如是說)。