$\newcommand{\O}{\mathrm{O}}$
準オイラーグラフ(一筆書きできるようなグラフ)かの判定および準オイラーグラフについては実際にオイラー路を求めるアルゴリズム(Hierholzer's Algorithm).
無向グラフの場合と有向グラフの場合の $2$ つのコードを置いています.
(注) グラフが連結であることを仮定しています.
(関数)
solve(): 準オイラーグラフかどうか(true/false)を返し, true なら $ans$ にオイラー路が格納される
時間計算量: $\O (m)$
class EulerPath { private: struct edge { int to; list<edge>::const_iterator rev; edge(int to_) : to(to_){} }; public: int V; list<edge>* G; vector<int> ans; EulerPath(int node_size) : V(node_size){ G = new list<edge>[V]; } void add_edge(int u, int v){ G[u].push_back((edge){v}); list<edge>::const_iterator revu = (--G[u].end()); G[v].push_back((edge){u}); list<edge>::const_iterator revv = (--G[v].end()); G[u].back().rev = revv, G[v].back().rev = revu; } int judge(){ int s = -1, odd = 0; for(int i = 0; i < V; i++){ if((int)G[i].size() % 2){ if(++odd >= 3) return -1; s = i; } } return max(s, 0); } bool solve(){ int cur = judge(); if(V == 0 || cur < 0) return false; stack<int> cur_path; cur_path.push(cur); while(!cur_path.empty()){ if(!G[cur].empty()){ cur_path.push(cur); auto nx = G[cur].back(); G[cur].pop_back(), G[nx.to].erase(nx.rev); cur = nx.to; }else{ ans.push_back(cur); cur = cur_path.top(), cur_path.pop(); } } return true; } };
class EulerPath { public: int V; vector<vector<int> > G; vector<int> degree, ans; EulerPath(int node_size) : V(node_size), G(V), degree(V, 0){} void add_edge(int u, int v){ G[u].push_back(v), degree[u]++, degree[v]--; } int judge(){ int s = -1; bool out = false, in = false; for(int i = 0; i < V; i++){ if(degree[i] == 0) continue; if(degree[i] == 1){ if(out) return -1; out = true, s = i; }else if(degree[i] == -1){ if(in) return -1; in = true; }else return -1; } return max(s, 0); } bool solve(){ int cur = judge(); if(V == 0 || cur < 0) return false; stack<int> cur_path; cur_path.push(cur); while(!cur_path.empty()){ if(!G[cur].empty()){ cur_path.push(cur); int nx = G[cur].back(); G[cur].pop_back(); cur = nx; }else{ ans.push_back(cur); cur = cur_path.top(), cur_path.pop(); } } reverse(ans.begin(), ans.end()); return true; } };
Codeforces : Neko and Flashback 提出コード(無向の場合)