|
1 /* -*- C++ -*- |
|
2 * lemon/topology.h - Part of LEMON, a generic C++ optimization library |
|
3 * |
|
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
|
5 * (Egervary Research Group on Combinatorial Optimization, EGRES). |
|
6 * |
|
7 * Permission to use, modify and distribute this software is granted |
|
8 * provided that this copyright notice appears in all copies. For |
|
9 * precise terms see the accompanying LICENSE file. |
|
10 * |
|
11 * This software is provided "AS IS" with no warranty of any kind, |
|
12 * express or implied, and with no claim as to its suitability for any |
|
13 * purpose. |
|
14 * |
|
15 */ |
|
16 #include<lemon/invalid.h> |
|
17 #include <list> |
|
18 |
|
19 /// \ingroup gutils |
|
20 /// \file |
|
21 /// \brief Euler tour |
|
22 /// |
|
23 ///This file provides an Euler tour iterator and ways to check |
|
24 ///if a graph is euler. |
|
25 |
|
26 |
|
27 namespace lemon { |
|
28 |
|
29 ///Euler iterator in directed graphs. |
|
30 |
|
31 /// \ingroup gutils |
|
32 ///This iterator converts to the \c Edge type of the graph and using |
|
33 ///the ++ operator it provides an Euler tour of the graph (if there exists). |
|
34 /// |
|
35 ///For example |
|
36 ///if the given graph if Euler (i.e it has only one nontrivial component |
|
37 ///and the in-degree is equal to the out-degree for all nodes), |
|
38 ///the the following code will print the edge IDs according to an |
|
39 ///Euler tour of \c g. |
|
40 ///\code |
|
41 /// for(EulerIt<ListGraph> e(g),e!=INVALID;++e) { |
|
42 /// std::cout << g.id(e) << std::eol; |
|
43 /// } |
|
44 ///\endcode |
|
45 ///If \c g is not Euler then the resulted tour will not be full or closed. |
|
46 ///\todo Test required |
|
47 template<class Graph> |
|
48 class EulerIt |
|
49 { |
|
50 typedef typename Graph::Node Node; |
|
51 typedef typename Graph::NodeIt NodeIt; |
|
52 typedef typename Graph::Edge Edge; |
|
53 typedef typename Graph::EdgeIt EdgeIt; |
|
54 typedef typename Graph::OutEdgeIt OutEdgeIt; |
|
55 typedef typename Graph::InEdgeIt InEdgeIt; |
|
56 |
|
57 const Graph &g; |
|
58 typename Graph::NodeMap<OutEdgeIt> nedge; |
|
59 std::list<Edge> euler; |
|
60 |
|
61 public: |
|
62 |
|
63 ///Constructor |
|
64 |
|
65 ///\param _g A directed graph. |
|
66 ///\param start The starting point of the tour. If it is not given |
|
67 /// tho tour will start from the first node. |
|
68 EulerIt(const Graph &_g,typename Graph::Node start=INVALID) |
|
69 : g(_g), nedge(g) |
|
70 { |
|
71 if(start==INVALID) start=NodeIt(g); |
|
72 for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutEdgeIt(g,n); |
|
73 while(nedge[start]!=INVALID) { |
|
74 euler.push_back(nedge[start]); |
|
75 Node next=g.target(nedge[start]); |
|
76 ++nedge[start]; |
|
77 start=next; |
|
78 } |
|
79 } |
|
80 |
|
81 ///Edge Conversion |
|
82 operator Edge() { return euler.empty()?INVALID:euler.front(); } |
|
83 bool operator==(Invalid) { return euler.empty(); } |
|
84 bool operator!=(Invalid) { return !euler.empty(); } |
|
85 |
|
86 ///Next edge of the tour |
|
87 EulerIt &operator++() { |
|
88 Node s=g.target(euler.front()); |
|
89 euler.pop_front(); |
|
90 //This produces a warning.Strange. |
|
91 //std::list<Edge>::iterator next=euler.begin(); |
|
92 typename std::list<Edge>::iterator next=euler.begin(); |
|
93 while(nedge[s]!=INVALID) { |
|
94 euler.insert(next,nedge[s]); |
|
95 Node n=g.target(nedge[s]); |
|
96 ++nedge[s]; |
|
97 s=n; |
|
98 } |
|
99 return *this; |
|
100 } |
|
101 ///Postfix incrementation |
|
102 |
|
103 ///\warning This gives back an Edge, not an EulerIt! |
|
104 ///\todo Is this what we want? |
|
105 Edge operator++(int) |
|
106 { |
|
107 Edge e=*this; |
|
108 ++(*this); |
|
109 return e; |
|
110 } |
|
111 }; |
|
112 |
|
113 ///Checks if the graph is Euler |
|
114 |
|
115 /// \ingroup gutils |
|
116 ///Checks if the graph is Euler. It works for both directed and |
|
117 ///undirected graphs. |
|
118 ///\todo What to do with the isolated points? |
|
119 ///\todo Test required |
|
120 template<class Graph> |
|
121 #ifdef DOXYGEN |
|
122 bool |
|
123 #else |
|
124 typename enable_if<typename Graph::UndirTag,bool>::type |
|
125 #endif |
|
126 euler(const Graph &g) |
|
127 { |
|
128 for(typename Graph::NodeIt n(g);n!=INVALID;++n) |
|
129 if(countIncEdges(g,n)%2) return false; |
|
130 return true; |
|
131 } |
|
132 template<class Graph> |
|
133 typename disable_if<typename Graph::UndirTag,bool>::type |
|
134 isEuler(const Graph &g) |
|
135 { |
|
136 for(typename Graph::NodeIt n(g);n!=INVALID;++n) |
|
137 if(countInEdges(g,n)!=countOutEdges(g,n)) return false; |
|
138 return true; |
|
139 } |
|
140 |
|
141 } |