TOP > グラフ オイラー路 オイラー路(Eulerian-Trail) 2019/05/15 • ei1333 説明 有向/無向グラフが与えられたときに、グラフの全ての辺をちょうど $1$ 回ずつ通る路を求める。 計算量 $O(E)$ 実装例 eulerian-trail($es$, $s$, $directed$):= 辺集合 $es$ 上で、頂点 $s$ から始まるオイラー路を求める。$directed = false$ のとき無向、$true$ のとき有向グラフとして扱う。 template< typename T > vector< edge< T > > eulerian_path(Edges< T > es, int s, bool directed) { int V = 0; for(auto &e : es) V = max(V, max(e.to, e.src) + 1); vector< vector< pair< edge< T >, int > > > g(V); for(auto &e : es) { int sz_to = (int) g[e.to].size(); g[e.src].emplace_back(e, sz_to); if(!directed) { int sz_src = (int) g[e.src].size() - 1; swap(e.src, e.to); g[e.src].emplace_back(e, sz_src); } } vector< edge< T > > ord; stack< pair< int, edge< T > > > st; st.emplace(s, edge< T >(-1, -1)); while(st.size()) { int idx = st.top().first; if(g[idx].empty()) { ord.emplace_back(st.top().second); st.pop(); } else { auto e = g[idx].back(); g[idx].pop_back(); if(e.second == -1) continue; if(!directed) g[e.first.to][e.second].second = -1; st.emplace(e.first.to, e.first); } } ord.pop_back(); reverse(begin(ord), end(ord)); if(ord.size() != es.size()) return {}; return ord; }