|
1 /* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
2 * |
|
3 * This file is a part of LEMON, a generic C++ optimization library. |
|
4 * |
|
5 * Copyright (C) 2003-2010 |
|
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
|
7 * (Egervary Research Group on Combinatorial Optimization, EGRES). |
|
8 * |
|
9 * Permission to use, modify and distribute this software is granted |
|
10 * provided that this copyright notice appears in all copies. For |
|
11 * precise terms see the accompanying LICENSE file. |
|
12 * |
|
13 * This software is provided "AS IS" with no warranty of any kind, |
|
14 * express or implied, and with no claim as to its suitability for any |
|
15 * purpose. |
|
16 * |
|
17 */ |
|
18 |
|
19 #ifndef LEMON_NAGAMOCHI_IBARAKI_H |
|
20 #define LEMON_NAGAMOCHI_IBARAKI_H |
|
21 |
|
22 |
|
23 /// \ingroup min_cut |
|
24 /// \file |
|
25 /// \brief Implementation of the Nagamochi-Ibaraki algorithm. |
|
26 |
|
27 #include <lemon/core.h> |
|
28 #include <lemon/bin_heap.h> |
|
29 #include <lemon/bucket_heap.h> |
|
30 #include <lemon/maps.h> |
|
31 #include <lemon/radix_sort.h> |
|
32 #include <lemon/unionfind.h> |
|
33 |
|
34 #include <cassert> |
|
35 |
|
36 namespace lemon { |
|
37 |
|
38 /// \brief Default traits class for NagamochiIbaraki class. |
|
39 /// |
|
40 /// Default traits class for NagamochiIbaraki class. |
|
41 /// \param GR The undirected graph type. |
|
42 /// \param CM Type of capacity map. |
|
43 template <typename GR, typename CM> |
|
44 struct NagamochiIbarakiDefaultTraits { |
|
45 /// The type of the capacity map. |
|
46 typedef typename CM::Value Value; |
|
47 |
|
48 /// The undirected graph type the algorithm runs on. |
|
49 typedef GR Graph; |
|
50 |
|
51 /// \brief The type of the map that stores the edge capacities. |
|
52 /// |
|
53 /// The type of the map that stores the edge capacities. |
|
54 /// It must meet the \ref concepts::ReadMap "ReadMap" concept. |
|
55 typedef CM CapacityMap; |
|
56 |
|
57 /// \brief Instantiates a CapacityMap. |
|
58 /// |
|
59 /// This function instantiates a \ref CapacityMap. |
|
60 #ifdef DOXYGEN |
|
61 static CapacityMap *createCapacityMap(const Graph& graph) |
|
62 #else |
|
63 static CapacityMap *createCapacityMap(const Graph&) |
|
64 #endif |
|
65 { |
|
66 LEMON_ASSERT(false, "CapacityMap is not initialized"); |
|
67 return 0; // ignore warnings |
|
68 } |
|
69 |
|
70 /// \brief The cross reference type used by heap. |
|
71 /// |
|
72 /// The cross reference type used by heap. |
|
73 /// Usually \c Graph::NodeMap<int>. |
|
74 typedef typename Graph::template NodeMap<int> HeapCrossRef; |
|
75 |
|
76 /// \brief Instantiates a HeapCrossRef. |
|
77 /// |
|
78 /// This function instantiates a \ref HeapCrossRef. |
|
79 /// \param g is the graph, to which we would like to define the |
|
80 /// \ref HeapCrossRef. |
|
81 static HeapCrossRef *createHeapCrossRef(const Graph& g) { |
|
82 return new HeapCrossRef(g); |
|
83 } |
|
84 |
|
85 /// \brief The heap type used by NagamochiIbaraki algorithm. |
|
86 /// |
|
87 /// The heap type used by NagamochiIbaraki algorithm. It has to |
|
88 /// maximize the priorities. |
|
89 /// |
|
90 /// \sa BinHeap |
|
91 /// \sa NagamochiIbaraki |
|
92 typedef BinHeap<Value, HeapCrossRef, std::greater<Value> > Heap; |
|
93 |
|
94 /// \brief Instantiates a Heap. |
|
95 /// |
|
96 /// This function instantiates a \ref Heap. |
|
97 /// \param r is the cross reference of the heap. |
|
98 static Heap *createHeap(HeapCrossRef& r) { |
|
99 return new Heap(r); |
|
100 } |
|
101 }; |
|
102 |
|
103 /// \ingroup min_cut |
|
104 /// |
|
105 /// \brief Calculates the minimum cut in an undirected graph. |
|
106 /// |
|
107 /// Calculates the minimum cut in an undirected graph with the |
|
108 /// Nagamochi-Ibaraki algorithm. The algorithm separates the graph's |
|
109 /// nodes into two partitions with the minimum sum of edge capacities |
|
110 /// between the two partitions. The algorithm can be used to test |
|
111 /// the network reliability, especially to test how many links have |
|
112 /// to be destroyed in the network to split it to at least two |
|
113 /// distinict subnetworks. |
|
114 /// |
|
115 /// The complexity of the algorithm is \f$ O(nm\log(n)) \f$ but with |
|
116 /// \ref FibHeap "Fibonacci heap" it can be decreased to |
|
117 /// \f$ O(nm+n^2\log(n)) \f$. When the edges have unit capacities, |
|
118 /// \c BucketHeap can be used which yields \f$ O(nm) \f$ time |
|
119 /// complexity. |
|
120 /// |
|
121 /// \warning The value type of the capacity map should be able to |
|
122 /// hold any cut value of the graph, otherwise the result can |
|
123 /// overflow. |
|
124 /// \note This capacity is supposed to be integer type. |
|
125 #ifdef DOXYGEN |
|
126 template <typename GR, typename CM, typename TR> |
|
127 #else |
|
128 template <typename GR, |
|
129 typename CM = typename GR::template EdgeMap<int>, |
|
130 typename TR = NagamochiIbarakiDefaultTraits<GR, CM> > |
|
131 #endif |
|
132 class NagamochiIbaraki { |
|
133 public: |
|
134 |
|
135 typedef TR Traits; |
|
136 /// The type of the underlying graph. |
|
137 typedef typename Traits::Graph Graph; |
|
138 |
|
139 /// The type of the capacity map. |
|
140 typedef typename Traits::CapacityMap CapacityMap; |
|
141 /// The value type of the capacity map. |
|
142 typedef typename Traits::CapacityMap::Value Value; |
|
143 |
|
144 /// The heap type used by the algorithm. |
|
145 typedef typename Traits::Heap Heap; |
|
146 /// The cross reference type used for the heap. |
|
147 typedef typename Traits::HeapCrossRef HeapCrossRef; |
|
148 |
|
149 ///\name Named template parameters |
|
150 |
|
151 ///@{ |
|
152 |
|
153 struct SetUnitCapacityTraits : public Traits { |
|
154 typedef ConstMap<typename Graph::Edge, Const<int, 1> > CapacityMap; |
|
155 static CapacityMap *createCapacityMap(const Graph&) { |
|
156 return new CapacityMap(); |
|
157 } |
|
158 }; |
|
159 |
|
160 /// \brief \ref named-templ-param "Named parameter" for setting |
|
161 /// the capacity map to a constMap<Edge, int, 1>() instance |
|
162 /// |
|
163 /// \ref named-templ-param "Named parameter" for setting |
|
164 /// the capacity map to a constMap<Edge, int, 1>() instance |
|
165 struct SetUnitCapacity |
|
166 : public NagamochiIbaraki<Graph, CapacityMap, |
|
167 SetUnitCapacityTraits> { |
|
168 typedef NagamochiIbaraki<Graph, CapacityMap, |
|
169 SetUnitCapacityTraits> Create; |
|
170 }; |
|
171 |
|
172 |
|
173 template <class H, class CR> |
|
174 struct SetHeapTraits : public Traits { |
|
175 typedef CR HeapCrossRef; |
|
176 typedef H Heap; |
|
177 static HeapCrossRef *createHeapCrossRef(int num) { |
|
178 LEMON_ASSERT(false, "HeapCrossRef is not initialized"); |
|
179 return 0; // ignore warnings |
|
180 } |
|
181 static Heap *createHeap(HeapCrossRef &) { |
|
182 LEMON_ASSERT(false, "Heap is not initialized"); |
|
183 return 0; // ignore warnings |
|
184 } |
|
185 }; |
|
186 |
|
187 /// \brief \ref named-templ-param "Named parameter" for setting |
|
188 /// heap and cross reference type |
|
189 /// |
|
190 /// \ref named-templ-param "Named parameter" for setting heap and |
|
191 /// cross reference type. The heap has to maximize the priorities. |
|
192 template <class H, class CR = RangeMap<int> > |
|
193 struct SetHeap |
|
194 : public NagamochiIbaraki<Graph, CapacityMap, SetHeapTraits<H, CR> > { |
|
195 typedef NagamochiIbaraki< Graph, CapacityMap, SetHeapTraits<H, CR> > |
|
196 Create; |
|
197 }; |
|
198 |
|
199 template <class H, class CR> |
|
200 struct SetStandardHeapTraits : public Traits { |
|
201 typedef CR HeapCrossRef; |
|
202 typedef H Heap; |
|
203 static HeapCrossRef *createHeapCrossRef(int size) { |
|
204 return new HeapCrossRef(size); |
|
205 } |
|
206 static Heap *createHeap(HeapCrossRef &crossref) { |
|
207 return new Heap(crossref); |
|
208 } |
|
209 }; |
|
210 |
|
211 /// \brief \ref named-templ-param "Named parameter" for setting |
|
212 /// heap and cross reference type with automatic allocation |
|
213 /// |
|
214 /// \ref named-templ-param "Named parameter" for setting heap and |
|
215 /// cross reference type with automatic allocation. They should |
|
216 /// have standard constructor interfaces to be able to |
|
217 /// automatically created by the algorithm (i.e. the graph should |
|
218 /// be passed to the constructor of the cross reference and the |
|
219 /// cross reference should be passed to the constructor of the |
|
220 /// heap). However, external heap and cross reference objects |
|
221 /// could also be passed to the algorithm using the \ref heap() |
|
222 /// function before calling \ref run() or \ref init(). The heap |
|
223 /// has to maximize the priorities. |
|
224 /// \sa SetHeap |
|
225 template <class H, class CR = RangeMap<int> > |
|
226 struct SetStandardHeap |
|
227 : public NagamochiIbaraki<Graph, CapacityMap, |
|
228 SetStandardHeapTraits<H, CR> > { |
|
229 typedef NagamochiIbaraki<Graph, CapacityMap, |
|
230 SetStandardHeapTraits<H, CR> > Create; |
|
231 }; |
|
232 |
|
233 ///@} |
|
234 |
|
235 |
|
236 private: |
|
237 |
|
238 const Graph &_graph; |
|
239 const CapacityMap *_capacity; |
|
240 bool _local_capacity; // unit capacity |
|
241 |
|
242 struct ArcData { |
|
243 typename Graph::Node target; |
|
244 int prev, next; |
|
245 }; |
|
246 struct EdgeData { |
|
247 Value capacity; |
|
248 Value cut; |
|
249 }; |
|
250 |
|
251 struct NodeData { |
|
252 int first_arc; |
|
253 typename Graph::Node prev, next; |
|
254 int curr_arc; |
|
255 typename Graph::Node last_rep; |
|
256 Value sum; |
|
257 }; |
|
258 |
|
259 typename Graph::template NodeMap<NodeData> *_nodes; |
|
260 std::vector<ArcData> _arcs; |
|
261 std::vector<EdgeData> _edges; |
|
262 |
|
263 typename Graph::Node _first_node; |
|
264 int _node_num; |
|
265 |
|
266 Value _min_cut; |
|
267 |
|
268 HeapCrossRef *_heap_cross_ref; |
|
269 bool _local_heap_cross_ref; |
|
270 Heap *_heap; |
|
271 bool _local_heap; |
|
272 |
|
273 typedef typename Graph::template NodeMap<typename Graph::Node> NodeList; |
|
274 NodeList *_next_rep; |
|
275 |
|
276 typedef typename Graph::template NodeMap<bool> MinCutMap; |
|
277 MinCutMap *_cut_map; |
|
278 |
|
279 void createStructures() { |
|
280 if (!_nodes) { |
|
281 _nodes = new (typename Graph::template NodeMap<NodeData>)(_graph); |
|
282 } |
|
283 if (!_capacity) { |
|
284 _local_capacity = true; |
|
285 _capacity = Traits::createCapacityMap(_graph); |
|
286 } |
|
287 if (!_heap_cross_ref) { |
|
288 _local_heap_cross_ref = true; |
|
289 _heap_cross_ref = Traits::createHeapCrossRef(_graph); |
|
290 } |
|
291 if (!_heap) { |
|
292 _local_heap = true; |
|
293 _heap = Traits::createHeap(*_heap_cross_ref); |
|
294 } |
|
295 if (!_next_rep) { |
|
296 _next_rep = new NodeList(_graph); |
|
297 } |
|
298 if (!_cut_map) { |
|
299 _cut_map = new MinCutMap(_graph); |
|
300 } |
|
301 } |
|
302 |
|
303 public : |
|
304 |
|
305 typedef NagamochiIbaraki Create; |
|
306 |
|
307 |
|
308 /// \brief Constructor. |
|
309 /// |
|
310 /// \param graph The graph the algorithm runs on. |
|
311 /// \param capacity The capacity map used by the algorithm. |
|
312 NagamochiIbaraki(const Graph& graph, const CapacityMap& capacity) |
|
313 : _graph(graph), _capacity(&capacity), _local_capacity(false), |
|
314 _nodes(0), _arcs(), _edges(), _min_cut(), |
|
315 _heap_cross_ref(0), _local_heap_cross_ref(false), |
|
316 _heap(0), _local_heap(false), |
|
317 _next_rep(0), _cut_map(0) {} |
|
318 |
|
319 /// \brief Constructor. |
|
320 /// |
|
321 /// This constructor can be used only when the Traits class |
|
322 /// defines how can the local capacity map be instantiated. |
|
323 /// If the SetUnitCapacity used the algorithm automatically |
|
324 /// constructs the capacity map. |
|
325 /// |
|
326 ///\param graph The graph the algorithm runs on. |
|
327 NagamochiIbaraki(const Graph& graph) |
|
328 : _graph(graph), _capacity(0), _local_capacity(false), |
|
329 _nodes(0), _arcs(), _edges(), _min_cut(), |
|
330 _heap_cross_ref(0), _local_heap_cross_ref(false), |
|
331 _heap(0), _local_heap(false), |
|
332 _next_rep(0), _cut_map(0) {} |
|
333 |
|
334 /// \brief Destructor. |
|
335 /// |
|
336 /// Destructor. |
|
337 ~NagamochiIbaraki() { |
|
338 if (_local_capacity) delete _capacity; |
|
339 if (_nodes) delete _nodes; |
|
340 if (_local_heap) delete _heap; |
|
341 if (_local_heap_cross_ref) delete _heap_cross_ref; |
|
342 if (_next_rep) delete _next_rep; |
|
343 if (_cut_map) delete _cut_map; |
|
344 } |
|
345 |
|
346 /// \brief Sets the heap and the cross reference used by algorithm. |
|
347 /// |
|
348 /// Sets the heap and the cross reference used by algorithm. |
|
349 /// If you don't use this function before calling \ref run(), |
|
350 /// it will allocate one. The destuctor deallocates this |
|
351 /// automatically allocated heap and cross reference, of course. |
|
352 /// \return <tt> (*this) </tt> |
|
353 NagamochiIbaraki &heap(Heap& hp, HeapCrossRef &cr) |
|
354 { |
|
355 if (_local_heap_cross_ref) { |
|
356 delete _heap_cross_ref; |
|
357 _local_heap_cross_ref = false; |
|
358 } |
|
359 _heap_cross_ref = &cr; |
|
360 if (_local_heap) { |
|
361 delete _heap; |
|
362 _local_heap = false; |
|
363 } |
|
364 _heap = &hp; |
|
365 return *this; |
|
366 } |
|
367 |
|
368 /// \name Execution control |
|
369 /// The simplest way to execute the algorithm is to use |
|
370 /// one of the member functions called \c run(). |
|
371 /// \n |
|
372 /// If you need more control on the execution, |
|
373 /// first you must call \ref init() and then call the start() |
|
374 /// or proper times the processNextPhase() member functions. |
|
375 |
|
376 ///@{ |
|
377 |
|
378 /// \brief Initializes the internal data structures. |
|
379 /// |
|
380 /// Initializes the internal data structures. |
|
381 void init() { |
|
382 createStructures(); |
|
383 |
|
384 int edge_num = countEdges(_graph); |
|
385 _edges.resize(edge_num); |
|
386 _arcs.resize(2 * edge_num); |
|
387 |
|
388 typename Graph::Node prev = INVALID; |
|
389 _node_num = 0; |
|
390 for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) { |
|
391 (*_cut_map)[n] = false; |
|
392 (*_next_rep)[n] = INVALID; |
|
393 (*_nodes)[n].last_rep = n; |
|
394 (*_nodes)[n].first_arc = -1; |
|
395 (*_nodes)[n].curr_arc = -1; |
|
396 (*_nodes)[n].prev = prev; |
|
397 if (prev != INVALID) { |
|
398 (*_nodes)[prev].next = n; |
|
399 } |
|
400 (*_nodes)[n].next = INVALID; |
|
401 (*_nodes)[n].sum = 0; |
|
402 prev = n; |
|
403 ++_node_num; |
|
404 } |
|
405 |
|
406 _first_node = typename Graph::NodeIt(_graph); |
|
407 |
|
408 int index = 0; |
|
409 for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) { |
|
410 for (typename Graph::OutArcIt a(_graph, n); a != INVALID; ++a) { |
|
411 typename Graph::Node m = _graph.target(a); |
|
412 |
|
413 if (!(n < m)) continue; |
|
414 |
|
415 (*_nodes)[n].sum += (*_capacity)[a]; |
|
416 (*_nodes)[m].sum += (*_capacity)[a]; |
|
417 |
|
418 int c = (*_nodes)[m].curr_arc; |
|
419 if (c != -1 && _arcs[c ^ 1].target == n) { |
|
420 _edges[c >> 1].capacity += (*_capacity)[a]; |
|
421 } else { |
|
422 _edges[index].capacity = (*_capacity)[a]; |
|
423 |
|
424 _arcs[index << 1].prev = -1; |
|
425 if ((*_nodes)[n].first_arc != -1) { |
|
426 _arcs[(*_nodes)[n].first_arc].prev = (index << 1); |
|
427 } |
|
428 _arcs[index << 1].next = (*_nodes)[n].first_arc; |
|
429 (*_nodes)[n].first_arc = (index << 1); |
|
430 _arcs[index << 1].target = m; |
|
431 |
|
432 (*_nodes)[m].curr_arc = (index << 1); |
|
433 |
|
434 _arcs[(index << 1) | 1].prev = -1; |
|
435 if ((*_nodes)[m].first_arc != -1) { |
|
436 _arcs[(*_nodes)[m].first_arc].prev = ((index << 1) | 1); |
|
437 } |
|
438 _arcs[(index << 1) | 1].next = (*_nodes)[m].first_arc; |
|
439 (*_nodes)[m].first_arc = ((index << 1) | 1); |
|
440 _arcs[(index << 1) | 1].target = n; |
|
441 |
|
442 ++index; |
|
443 } |
|
444 } |
|
445 } |
|
446 |
|
447 typename Graph::Node cut_node = INVALID; |
|
448 _min_cut = std::numeric_limits<Value>::max(); |
|
449 |
|
450 for (typename Graph::Node n = _first_node; |
|
451 n != INVALID; n = (*_nodes)[n].next) { |
|
452 if ((*_nodes)[n].sum < _min_cut) { |
|
453 cut_node = n; |
|
454 _min_cut = (*_nodes)[n].sum; |
|
455 } |
|
456 } |
|
457 (*_cut_map)[cut_node] = true; |
|
458 if (_min_cut == 0) { |
|
459 _first_node = INVALID; |
|
460 } |
|
461 } |
|
462 |
|
463 public: |
|
464 |
|
465 /// \brief Processes the next phase |
|
466 /// |
|
467 /// Processes the next phase in the algorithm. It must be called |
|
468 /// at most one less the number of the nodes in the graph. |
|
469 /// |
|
470 ///\return %True when the algorithm finished. |
|
471 bool processNextPhase() { |
|
472 if (_first_node == INVALID) return true; |
|
473 |
|
474 _heap->clear(); |
|
475 for (typename Graph::Node n = _first_node; |
|
476 n != INVALID; n = (*_nodes)[n].next) { |
|
477 (*_heap_cross_ref)[n] = Heap::PRE_HEAP; |
|
478 } |
|
479 |
|
480 std::vector<typename Graph::Node> order; |
|
481 order.reserve(_node_num); |
|
482 int sep = 0; |
|
483 |
|
484 Value alpha = 0; |
|
485 Value pmc = std::numeric_limits<Value>::max(); |
|
486 |
|
487 _heap->push(_first_node, static_cast<Value>(0)); |
|
488 while (!_heap->empty()) { |
|
489 typename Graph::Node n = _heap->top(); |
|
490 Value v = _heap->prio(); |
|
491 |
|
492 _heap->pop(); |
|
493 for (int a = (*_nodes)[n].first_arc; a != -1; a = _arcs[a].next) { |
|
494 switch (_heap->state(_arcs[a].target)) { |
|
495 case Heap::PRE_HEAP: |
|
496 { |
|
497 Value nv = _edges[a >> 1].capacity; |
|
498 _heap->push(_arcs[a].target, nv); |
|
499 _edges[a >> 1].cut = nv; |
|
500 } break; |
|
501 case Heap::IN_HEAP: |
|
502 { |
|
503 Value nv = _edges[a >> 1].capacity + (*_heap)[_arcs[a].target]; |
|
504 _heap->decrease(_arcs[a].target, nv); |
|
505 _edges[a >> 1].cut = nv; |
|
506 } break; |
|
507 case Heap::POST_HEAP: |
|
508 break; |
|
509 } |
|
510 } |
|
511 |
|
512 alpha += (*_nodes)[n].sum; |
|
513 alpha -= 2 * v; |
|
514 |
|
515 order.push_back(n); |
|
516 if (!_heap->empty()) { |
|
517 if (alpha < pmc) { |
|
518 pmc = alpha; |
|
519 sep = order.size(); |
|
520 } |
|
521 } |
|
522 } |
|
523 |
|
524 if (static_cast<int>(order.size()) < _node_num) { |
|
525 _first_node = INVALID; |
|
526 for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) { |
|
527 (*_cut_map)[n] = false; |
|
528 } |
|
529 for (int i = 0; i < static_cast<int>(order.size()); ++i) { |
|
530 typename Graph::Node n = order[i]; |
|
531 while (n != INVALID) { |
|
532 (*_cut_map)[n] = true; |
|
533 n = (*_next_rep)[n]; |
|
534 } |
|
535 } |
|
536 _min_cut = 0; |
|
537 return true; |
|
538 } |
|
539 |
|
540 if (pmc < _min_cut) { |
|
541 for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) { |
|
542 (*_cut_map)[n] = false; |
|
543 } |
|
544 for (int i = 0; i < sep; ++i) { |
|
545 typename Graph::Node n = order[i]; |
|
546 while (n != INVALID) { |
|
547 (*_cut_map)[n] = true; |
|
548 n = (*_next_rep)[n]; |
|
549 } |
|
550 } |
|
551 _min_cut = pmc; |
|
552 } |
|
553 |
|
554 for (typename Graph::Node n = _first_node; |
|
555 n != INVALID; n = (*_nodes)[n].next) { |
|
556 bool merged = false; |
|
557 for (int a = (*_nodes)[n].first_arc; a != -1; a = _arcs[a].next) { |
|
558 if (!(_edges[a >> 1].cut < pmc)) { |
|
559 if (!merged) { |
|
560 for (int b = (*_nodes)[n].first_arc; b != -1; b = _arcs[b].next) { |
|
561 (*_nodes)[_arcs[b].target].curr_arc = b; |
|
562 } |
|
563 merged = true; |
|
564 } |
|
565 typename Graph::Node m = _arcs[a].target; |
|
566 int nb = 0; |
|
567 for (int b = (*_nodes)[m].first_arc; b != -1; b = nb) { |
|
568 nb = _arcs[b].next; |
|
569 if ((b ^ a) == 1) continue; |
|
570 typename Graph::Node o = _arcs[b].target; |
|
571 int c = (*_nodes)[o].curr_arc; |
|
572 if (c != -1 && _arcs[c ^ 1].target == n) { |
|
573 _edges[c >> 1].capacity += _edges[b >> 1].capacity; |
|
574 (*_nodes)[n].sum += _edges[b >> 1].capacity; |
|
575 if (_edges[b >> 1].cut < _edges[c >> 1].cut) { |
|
576 _edges[b >> 1].cut = _edges[c >> 1].cut; |
|
577 } |
|
578 if (_arcs[b ^ 1].prev != -1) { |
|
579 _arcs[_arcs[b ^ 1].prev].next = _arcs[b ^ 1].next; |
|
580 } else { |
|
581 (*_nodes)[o].first_arc = _arcs[b ^ 1].next; |
|
582 } |
|
583 if (_arcs[b ^ 1].next != -1) { |
|
584 _arcs[_arcs[b ^ 1].next].prev = _arcs[b ^ 1].prev; |
|
585 } |
|
586 } else { |
|
587 if (_arcs[a].next != -1) { |
|
588 _arcs[_arcs[a].next].prev = b; |
|
589 } |
|
590 _arcs[b].next = _arcs[a].next; |
|
591 _arcs[b].prev = a; |
|
592 _arcs[a].next = b; |
|
593 _arcs[b ^ 1].target = n; |
|
594 |
|
595 (*_nodes)[n].sum += _edges[b >> 1].capacity; |
|
596 (*_nodes)[o].curr_arc = b; |
|
597 } |
|
598 } |
|
599 |
|
600 if (_arcs[a].prev != -1) { |
|
601 _arcs[_arcs[a].prev].next = _arcs[a].next; |
|
602 } else { |
|
603 (*_nodes)[n].first_arc = _arcs[a].next; |
|
604 } |
|
605 if (_arcs[a].next != -1) { |
|
606 _arcs[_arcs[a].next].prev = _arcs[a].prev; |
|
607 } |
|
608 |
|
609 (*_nodes)[n].sum -= _edges[a >> 1].capacity; |
|
610 (*_next_rep)[(*_nodes)[n].last_rep] = m; |
|
611 (*_nodes)[n].last_rep = (*_nodes)[m].last_rep; |
|
612 |
|
613 if ((*_nodes)[m].prev != INVALID) { |
|
614 (*_nodes)[(*_nodes)[m].prev].next = (*_nodes)[m].next; |
|
615 } else{ |
|
616 _first_node = (*_nodes)[m].next; |
|
617 } |
|
618 if ((*_nodes)[m].next != INVALID) { |
|
619 (*_nodes)[(*_nodes)[m].next].prev = (*_nodes)[m].prev; |
|
620 } |
|
621 --_node_num; |
|
622 } |
|
623 } |
|
624 } |
|
625 |
|
626 if (_node_num == 1) { |
|
627 _first_node = INVALID; |
|
628 return true; |
|
629 } |
|
630 |
|
631 return false; |
|
632 } |
|
633 |
|
634 /// \brief Executes the algorithm. |
|
635 /// |
|
636 /// Executes the algorithm. |
|
637 /// |
|
638 /// \pre init() must be called |
|
639 void start() { |
|
640 while (!processNextPhase()) {} |
|
641 } |
|
642 |
|
643 |
|
644 /// \brief Runs %NagamochiIbaraki algorithm. |
|
645 /// |
|
646 /// This method runs the %Min cut algorithm |
|
647 /// |
|
648 /// \note mc.run(s) is just a shortcut of the following code. |
|
649 ///\code |
|
650 /// mc.init(); |
|
651 /// mc.start(); |
|
652 ///\endcode |
|
653 void run() { |
|
654 init(); |
|
655 start(); |
|
656 } |
|
657 |
|
658 ///@} |
|
659 |
|
660 /// \name Query Functions |
|
661 /// |
|
662 /// The result of the %NagamochiIbaraki |
|
663 /// algorithm can be obtained using these functions.\n |
|
664 /// Before the use of these functions, either run() or start() |
|
665 /// must be called. |
|
666 |
|
667 ///@{ |
|
668 |
|
669 /// \brief Returns the min cut value. |
|
670 /// |
|
671 /// Returns the min cut value if the algorithm finished. |
|
672 /// After the first processNextPhase() it is a value of a |
|
673 /// valid cut in the graph. |
|
674 Value minCutValue() const { |
|
675 return _min_cut; |
|
676 } |
|
677 |
|
678 /// \brief Returns a min cut in a NodeMap. |
|
679 /// |
|
680 /// It sets the nodes of one of the two partitions to true and |
|
681 /// the other partition to false. |
|
682 /// \param cutMap A \ref concepts::WriteMap "writable" node map with |
|
683 /// \c bool (or convertible) value type. |
|
684 template <typename CutMap> |
|
685 Value minCutMap(CutMap& cutMap) const { |
|
686 for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) { |
|
687 cutMap.set(n, (*_cut_map)[n]); |
|
688 } |
|
689 return minCutValue(); |
|
690 } |
|
691 |
|
692 ///@} |
|
693 |
|
694 }; |
|
695 } |
|
696 |
|
697 #endif |