Aleph-w  1.9
General library for algorithms and data structures
tpl_bipartite.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 # ifndef TPL_BIPARTITE_H
28 # define TPL_BIPARTITE_H
29 
30 # include <tpl_dynDlist.H>
31 # include <tpl_net.H>
32 
33 namespace Aleph {
34 
35 enum Bipartite_Color { Bp_White, Bp_Red, Bp_Blue };
36 
37  template <class GT>
38 static long & color(typename GT::Node * p)
39 {
40  return NODE_COUNTER(p);
41 }
42 
43  template <class GT>
44 static long & color(typename GT::Arc * a)
45 {
46  return ARC_COUNTER(a);
47 }
48 
67  template <class GT, class SA = Dft_Show_Arc<GT> >
68 void compute_bipartite(const GT & g,
71 {
72  g.reset_nodes(); // inicializa contadores en Blanco
73  g.reset_arcs();
74 
76  typename GT::Node * p = g.get_first_node();
77  color<GT>(p) = Bp_Red;
78  red.put(p); l.put(p);
79 
80  while (true)
81  if (not red.is_empty()) // ¿Hay rojo con arcos no mirados?
82  {
83  typename GT::Node * p = red.get();
84  for (Node_Arc_Iterator<GT, SA> it(p); it.has_curr(); it.next_ne())
85  {
86  typename GT::Arc * a = it.get_curr_ne();
87  if (color<GT>(a) == Bp_Red)
88  throw std::domain_error("Graph is not bipartite");
89  else if (color<GT>(a) == Bp_Blue)
90  continue;
91 
92  color<GT>(a) = Bp_Red;
93  typename GT::Node * q = it.get_tgt_node();
94  if (color<GT>(q) == Bp_Red)
95  throw std::domain_error("Graph is not bipartite");
96  else if (color<GT>(q) == Bp_Blue)
97  continue;
98 
99  color<GT>(q) = Bp_Blue;
100  blue.put(q); r.put(q);
101  }
102  }
103  else if (not blue.is_empty()) // ¿Hay azul con arcos no mirados?
104  {
105  typename GT::Node * p = blue.get();
106  for (Node_Arc_Iterator<GT, SA> it(p); it.has_curr(); it.next_ne())
107  {
108  typename GT::Arc * a = it.get_curr_ne();
109  if (color<GT>(a) == Bp_Blue)
110  throw std::domain_error("Graph is not bipartite");
111  else if (color<GT>(a) == Bp_Red)
112  continue;
113 
114  color<GT>(a) = Bp_Blue;
115 
116  typename GT::Node * q = it.get_tgt_node();
117  if (color<GT>(q) == Bp_Blue)
118  throw std::domain_error("Graph is not bipartite");
119  else if (color<GT>(q) == Bp_Red)
120  continue;
121 
122  color<GT>(q) = Bp_Red;
123  red.put(q); l.put(q);
124  }
125  }
126  else
127  break;
128 }
129 
138  template <class GT, class SA = Dft_Show_Arc<GT> >
140 {
141 public:
142 
152  void operator () (const GT & g,
155  {
156  compute_bipartite <GT, SA> (g, l, r);
157  }
158 };
159 
184  template <class GT,
185  template <class> class Max_Flow = Ford_Fulkerson_Maximum_Flow,
186  class SA = Dft_Show_Arc<GT>>
188  (const GT & g, DynDlist<typename GT::Arc *> & matching)
189 {
191 
192  compute_bipartite(g, l, r);
193 
195  AN net;
196 
197  // recorrer nodos de g e insertar imagen en net
198  for (Node_Iterator<GT> it(g); it.has_curr(); it.next_ne())
199  {
200  typename GT::Node * p = it.get_curr_ne();
201  NODE_COOKIE(p) = net.insert_node();
202  NODE_COOKIE((typename GT::Node *)NODE_COOKIE(p)) = p;
203  }
204 
205  typename AN::Node * source = net.insert_node();
206 
207  // recorrer nodos de l, atarlos a fuente e insertar sus arcos
208  for (typename DynDlist<typename GT::Node*>::Iterator i(l);
209  i.has_curr(); i.next_ne())
210  {
211  typename GT::Node * p = i.get_curr_ne();
212  typename AN::Node * src = mapped_node<GT, AN> (p);
213  net.insert_arc(source, src, 1);
214 
215  for (Node_Arc_Iterator<GT, SA> j(p); j.has_curr(); j.next_ne())
216  {
217  typename GT::Arc * arc = j.get_current_arc_ne();
218  typename AN::Node * tgt = mapped_node <GT, AN> (g.get_tgt_node(arc));
219  typename AN::Arc * a = net.insert_arc(src, tgt, 1);
220  ARC_COOKIE(arc) = a;
221  ARC_COOKIE(a) = arc;
222  }
223  }
224 
225  typename AN::Node * sink = net.insert_node();
226 
227  // recorrer nodos de r y atarlos al sumidero
228  for (typename DynDlist<typename GT::Node*>::Iterator it(r);
229  it.has_curr(); it.next_ne())
230  {
231  typename GT::Node * p = it.get_curr_ne();
232  net.insert_arc(mapped_node<GT, AN> (p), sink, 1);
233  }
234 
235  Max_Flow <AN> () (net);
236 
237  for (Arc_Iterator<AN> it(net); it.has_curr(); it.next_ne())
238  {
239  typename AN::Arc * a = it.get_curr_ne();
240  if (a->flow == 0)
241  continue;
242 
243  typename GT::Arc * arc = mapped_arc <AN, GT> (a);
244  if (arc == nullptr)
245  continue;
246 
247  matching.append(arc);
248  }
249 }
250 
263  template <class GT,
264  template <class> class Max_Flow = Ford_Fulkerson_Maximum_Flow,
265  class SA = Dft_Show_Arc<GT> >
267 {
268 public:
269 
285  void operator () (const GT & g, DynDlist<typename GT::Arc *> & matching)
286  {
287  compute_maximum_cardinality_bipartite_matching <GT, Max_Flow, SA>
288  (g, matching);
289  }
290 };
291 
292 
293 } // end namespace Aleph
294 
295 # endif // TPL_BIPARTITE_H
Definition: tpl_graph.H:1225
#define ARC_COUNTER(p)
Definition: aleph-graph.H:339
void operator()(const GT &g, DynDlist< typename GT::Node *> &l, DynDlist< typename GT::Node *> &r)
Definition: tpl_bipartite.H:152
#define NODE_COOKIE(p)
Definition: aleph-graph.H:333
Definition: tpl_dynDlist.H:51
void compute_bipartite(const GT &g, DynDlist< typename GT::Node *> &l, DynDlist< typename GT::Node *> &r)
Definition: tpl_bipartite.H:68
Definition: tpl_net.H:82
Definition: tpl_net.H:216
T & put(const T &item)
Definition: tpl_dynDlist.H:300
#define ARC_COOKIE(p)
Definition: aleph-graph.H:366
#define NODE_COUNTER(p)
Definition: aleph-graph.H:311
Definition: tpl_dynDlist.H:413
Definition: ah-comb.H:35
Definition: tpl_graph.H:1063
Definition: tpl_bipartite.H:139
Definition: tpl_net.H:1530
void compute_maximum_cardinality_bipartite_matching(const GT &g, DynDlist< typename GT::Arc *> &matching)
Definition: tpl_bipartite.H:188
Definition: tpl_graph.H:1270
T get()
Definition: tpl_dynDlist.H:306
Definition: tpl_graph.H:1177
T & append(const T &item)
Definition: tpl_dynDlist.H:149

Leandro Rabindranath León