Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
tpl_bipartite.H
1 # ifndef TPL_BIPARTITE_H
2 # define TPL_BIPARTITE_H
3 
4 # include <tpl_dynDlist.H>
5 # include <tpl_netgraph.H>
6 
7 namespace Aleph {
8 
9 enum Bipartite_Color { Bp_White, Bp_Red, Bp_Blue };
10 
11  template <class GT>
12 static long & color(typename GT::Node * p)
13 {
14  return NODE_COUNTER(p);
15 }
16 
17  template <class GT>
18 static long & color(typename GT::Arc * a)
19 {
20  return ARC_COUNTER(a);
21 }
22 
41  template <class GT, class SA = Dft_Show_Arc<GT> >
42 void compute_bipartite(GT & g,
45 {
46  g.reset_nodes(); // inicializa contadores en Blanco
47  g.reset_arcs();
48 
50  typename GT::Node * p = g.get_first_node();
51  color<GT>(p) = Bp_Red;
52  red.put(p); l.put(p);
53 
54  while (true)
55  if (not red.is_empty()) // ¿Hay rojo con arcos no mirados?
56  {
57  typename GT::Node * p = red.get();
58  for (Node_Arc_Iterator<GT, SA> it(p); it.has_current(); it.next())
59  {
60  typename GT::Arc * a = it.get_current();
61  if (color<GT>(a) == Bp_Red)
62  throw std::domain_error("Graph is not bipartite");
63  else if (color<GT>(a) == Bp_Blue)
64  continue;
65 
66  color<GT>(a) = Bp_Red;
67  typename GT::Node * q = it.get_tgt_node();
68  if (color<GT>(q) == Bp_Red)
69  throw std::domain_error("Graph is not bipartite");
70  else if (color<GT>(q) == Bp_Blue)
71  continue;
72 
73  color<GT>(q) = Bp_Blue;
74  blue.put(q); r.put(q);
75  }
76  }
77  else if (not blue.is_empty()) // ¿Hay azul con arcos no mirados?
78  {
79  typename GT::Node * p = blue.get();
80  for (Node_Arc_Iterator<GT, SA> it(p); it.has_current(); it.next())
81  {
82  typename GT::Arc * a = it.get_current();
83  if (color<GT>(a) == Bp_Blue)
84  throw std::domain_error("Graph is not bipartite");
85  else if (color<GT>(a) == Bp_Red)
86  continue;
87 
88  color<GT>(a) = Bp_Blue;
89 
90  typename GT::Node * q = it.get_tgt_node();
91  if (color<GT>(q) == Bp_Blue)
92  throw std::domain_error("Graph is not bipartite");
93  else if (color<GT>(q) == Bp_Red)
94  continue;
95 
96  color<GT>(q) = Bp_Red;
97  red.put(q); l.put(q);
98  }
99  }
100  else
101  break;
102 }
103 
112  template <class GT, class SA = Dft_Show_Arc<GT> >
114 {
115 public:
116 
126  void operator () (GT & g,
129  {
130  compute_bipartite <GT, SA> (g, l, r);
131  }
132 };
133 
158  template <class GT,
159  template <class> class Max_Flow = Ford_Fulkerson_Maximum_Flow,
160  class SA = Dft_Show_Arc<GT> >
162  (GT & g, DynDlist<typename GT::Arc *> & matching)
163 {
165 
166  compute_bipartite(g, l, r);
167 
169  AN net;
170 
171  // recorrer nodos de g e insertar imagen en net
172  for (Node_Iterator<GT> it(g); it.has_current(); it.next())
173  {
174  typename GT::Node * p = it.get_current();
175  NODE_COOKIE(p) = net.insert_node();
176  NODE_COOKIE((typename GT::Node *)NODE_COOKIE(p)) = p;
177  }
178 
179  typename AN::Node * source = net.insert_node();
180 
181  // recorrer nodos de l, atarlos a fuente e insertar sus arcos
182  for (typename DynDlist<typename GT::Node*>::Iterator i(l);
183  i.has_current(); i.next())
184  {
185  typename GT::Node * p = i.get_current();
186  typename AN::Node * src = mapped_node<GT, AN> (p);
187  net.insert_arc(source, src, 1);
188 
189  for (Node_Arc_Iterator<GT, SA> j(p); j.has_current(); j.next())
190  {
191  typename GT::Arc * arc = j.get_current_arc();
192  typename AN::Node * tgt = mapped_node <GT, AN> (g.get_tgt_node(arc));
193  typename AN::Arc * a = net.insert_arc(src, tgt, 1);
194  ARC_COOKIE(arc) = a;
195  ARC_COOKIE(a) = arc;
196  }
197  }
198 
199  typename AN::Node * sink = net.insert_node();
200 
201  // recorrer nodos de r y atarlos al sumidero
202  for (typename DynDlist<typename GT::Node*>::Iterator it(r);
203  it.has_current(); it.next())
204  {
205  typename GT::Node * p = it.get_current();
206  net.insert_arc(mapped_node<GT, AN> (p), sink, 1);
207  }
208 
209  Max_Flow <AN> () (net);
210 
211  for (Arc_Iterator<AN> it(net); it.has_current(); it.next())
212  {
213  typename AN::Arc * a = it.get_current();
214  if (a->flow == 0)
215  continue;
216 
217  typename GT::Arc * arc = mapped_arc <AN, GT> (a);
218  if (arc == NULL)
219  continue;
220 
221  matching.append(arc);
222  }
223 }
224 
237  template <class GT,
238  template <class> class Max_Flow = Ford_Fulkerson_Maximum_Flow,
239  class SA = Dft_Show_Arc<GT> >
241 {
242 public:
243 
260  {
261  compute_maximum_cardinality_bipartite_matching <GT, Max_Flow, SA>
262  (g, matching);
263  }
264 };
265 
266 
267 } // end namespace Aleph
268 
269 # endif // TPL_BIPARTITE_H
void compute_bipartite(GT &g, DynDlist< typename GT::Node * > &l, DynDlist< typename GT::Node * > &r)
Definition: tpl_bipartite.H:42
#define ARC_COUNTER(p)
Definition: aleph-graph.H:254
Definition: tpl_netgraph.H:66
#define NODE_COOKIE(p)
Definition: aleph-graph.H:248
Definition: tpl_graph.H:751
T & put(const T &item)
Si this es una cola, entonces mete el elemento item.
Definition: tpl_dynDlist.H:245
#define ARC_COOKIE(p)
Definition: aleph-graph.H:281
#define NODE_COUNTER(p)
Definition: aleph-graph.H:226
void operator()(GT &g, DynDlist< typename GT::Arc * > &matching)
Definition: tpl_bipartite.H:259
Definition: tpl_graph.H:634
void next()
Adelanta el iterador una posición.
Definition: filter_iterator.H:143
Definition: tpl_bipartite.H:113
void operator()(GT &g, DynDlist< typename GT::Node * > &l, DynDlist< typename GT::Node * > &r)
Definition: tpl_bipartite.H:126
Definition: tpl_netgraph.H:205
Definition: tpl_graph.H:814
Definition: tpl_netgraph.H:1231
T get()
Si this es una cola, entonces extrae el elemento más antiguo.
Definition: tpl_dynDlist.H:250
void compute_maximum_cardinality_bipartite_matching(GT &g, DynDlist< typename GT::Arc * > &matching)
Definition: tpl_bipartite.H:162
Definition: tpl_graph.H:694
T & append(const T &item)
Definition: tpl_dynDlist.H:106

Leandro Rabindranath León