// 無向圖的歐拉迴路線性時間演算法
// by rappizit@yahoo.com.cn
// 2007-11-02
#include <vector>
#include <list>
#include <stack>
#include <algorithm>
#include <iostream>
using namespace std;
#define pause system("pause")
typedef vector <int> vi;
typedef list <int> li;
typedef vector <li> vli;
vi EulerCircle (vli G)
{
int n = G.size ();
int edge = 0;
for (int i = 0; i < n; i ++)
{
int degree = G [i].size ();
if (degree % 2 || !degree)
{
return vi (0);
}
edge += degree;
}
vi path (edge / 2 + 1);
stack <int> s;
int p = 0, i = 0;
do {
if (G [i].empty ())
{
do {
s.pop ();
path [p ++] = i;
} while (!s.empty () && (i = s.top (), G [i].empty ()));
}
else {
int t = *(G [i].begin ());
G [i].erase (G [i].begin ());
G [t].erase (find (G [t].begin (), G [t].end (), i));
// 使用帶有十字連結的雙向鄰接表可以常數時間地刪除邊 e(t, i)?!
s.push (t);
i = t;
}
} while (!s.empty ());
return path;
}
void main ()
{
int n, m;
cin >> n >> m;
vli G (n);
while (m --)
{
int u, v;
cin >> u >> v;
G [u].push_back (v); // 這裡為了迎合書上的例子,每條無向邊分兩次輸入
}
vi path = EulerCircle (G);
if (path.size ())
{
for (int i = 0; i < path.size (); i ++)
{
cout << path [i] << " ";
}
cout << endl;
}
}
無向圖的歐拉迴路
採用鄰接表格儲存體,vector <list <int>> 類型。
1.如果某點的度數為奇數或零,則沒有歐拉迴路,返回空的 vector。
2.否則,從標號為 i = 0 的點開始。
3.如果 i 沒有鄰接點,那麼堆棧中所有沒有鄰接點的點彈出到 vector path 中,如果堆棧非空則 i 賦值為棧頂元素。
否則取 i 的第一個鄰接點 t ,刪除它們的邊(要在 G 中的兩處都刪除)。將 t 壓棧。i 賦值為 t 。
4.如果堆棧為空白,返回 path,否則轉 3。
演算法時間複雜度為 O (E)。
測試資料:
7 20
0 1
0 2
0 5
0 6
1 0
1 2
2 0
2 3
2 4
2 1
3 4
3 2
4 6
4 5
4 3
4 2
5 4
5 0
6 4
6 0
測試結果:
0 6 4 2 3 4 5 0 2 1 0
過程圖示:
First, the program adds the edge 0-1 to the tour and removes it from the adjacency lists (in two places) (top left, lists at left). Second, it adds 1-2 to the tour in the same way (left, second from top). Next, it winds up back at 0 but continues to do another cycle 0-5-4-6-0, winding up back at 0 with no more edges incident upon 0 (right, second from top). Then it pops the isolated vertices 0 and 6 from the stack until 4 is at the top and starts a tour from 4 (right, third from from top), which takes it to 3, 2, and back to 4, where upon it pops all the now-isolated vertices 4, 2, 3, and so forth. The sequence of vertices popped from the stack defines the Euler tour 0-6-4-2-3-4-5-0-2-1-0 of the whole graph.
參考來源:
Algorithms In Java, Part 5 Graph Algorithms , Chapter 17.7 / Java 演算法(第 3 版,第 2 卷)——圖演算法,章節 17.7
PS:但是我是用 C++ 實現的^_^