3 Copyright 2001 Vladimir Kolmogorov (vnk@cs.cornell.edu), Yuri Boykov (yuri@csd.uwo.ca).
\r
5 This program is free software; you can redistribute it and/or modify
\r
6 it under the terms of the GNU General Public License as published by
\r
7 the Free Software Foundation; either version 2 of the License, or
\r
8 (at your option) any later version.
\r
10 This program is distributed in the hope that it will be useful,
\r
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 GNU General Public License for more details.
\r
15 You should have received a copy of the GNU General Public License
\r
16 along with this program; if not, write to the Free Software
\r
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
25 special constants for node->parent
\r
27 #define TERMINAL ( (arc_forward *) 1 ) /* to terminal */
\r
28 #define ORPHAN ( (arc_forward *) 2 ) /* orphan */
\r
30 #define INFINITE_D 1000000000 /* infinite distance to the terminal */
\r
32 /***********************************************************************/
\r
35 Functions for processing active list.
\r
36 i->next points to the next node in the list
\r
37 (or to i, if i is the last node in the list).
\r
38 If i->next is NULL iff i is not in the list.
\r
40 There are two queues. Active nodes are added
\r
41 to the end of the second queue and read from
\r
42 the front of the first queue. If the first queue
\r
43 is empty, it is replaced by the second queue
\r
44 (and the second queue becomes empty).
\r
47 inline void Graph::set_active(node *i)
\r
51 /* it's not in the list yet */
\r
52 if (queue_last[1]) queue_last[1] -> next = i;
\r
53 else queue_first[1] = i;
\r
60 Returns the next active node.
\r
61 If it is connected to the sink, it stays in the list,
\r
62 otherwise it is removed from the list
\r
64 inline Graph::node * Graph::next_active()
\r
70 if (!(i=queue_first[0]))
\r
72 queue_first[0] = i = queue_first[1];
\r
73 queue_last[0] = queue_last[1];
\r
74 queue_first[1] = NULL;
\r
75 queue_last[1] = NULL;
\r
76 if (!i) return NULL;
\r
79 /* remove it from the active list */
\r
80 if (i->next == i) queue_first[0] = queue_last[0] = NULL;
\r
81 else queue_first[0] = i -> next;
\r
84 /* a node in the list is active iff it has a parent */
\r
85 if (i->parent) return i;
\r
89 /***********************************************************************/
\r
91 void Graph::maxflow_init()
\r
96 queue_first[0] = queue_last[0] = NULL;
\r
97 queue_first[1] = queue_last[1] = NULL;
\r
98 orphan_first = NULL;
\r
100 for (nb=node_block_first; nb; nb=nb->next)
\r
101 for (i=&nb->nodes[0]; i<nb->current; i++)
\r
107 /* i is connected to the source */
\r
109 i -> parent = TERMINAL;
\r
114 else if (i->tr_cap < 0)
\r
116 /* i is connected to the sink */
\r
118 i -> parent = TERMINAL;
\r
125 i -> parent = NULL;
\r
131 /***********************************************************************/
\r
133 void Graph::augment(node *s_start, node *t_start, captype *cap_middle, captype *rev_cap_middle)
\r
137 captype bottleneck;
\r
141 /* 1. Finding bottleneck capacity */
\r
142 /* 1a - the source tree */
\r
143 bottleneck = *cap_middle;
\r
144 for (i=s_start; ; )
\r
147 if (a == TERMINAL) break;
\r
151 if (bottleneck > a->r_cap) bottleneck = a -> r_cap;
\r
152 i = NEIGHBOR_NODE_REV(i, a -> shift);
\r
156 if (bottleneck > a->r_rev_cap) bottleneck = a -> r_rev_cap;
\r
157 i = NEIGHBOR_NODE(i, a -> shift);
\r
160 if (bottleneck > i->tr_cap) bottleneck = i -> tr_cap;
\r
161 /* 1b - the sink tree */
\r
162 for (i=t_start; ; )
\r
165 if (a == TERMINAL) break;
\r
169 if (bottleneck > a->r_rev_cap) bottleneck = a -> r_rev_cap;
\r
170 i = NEIGHBOR_NODE_REV(i, a -> shift);
\r
174 if (bottleneck > a->r_cap) bottleneck = a -> r_cap;
\r
175 i = NEIGHBOR_NODE(i, a -> shift);
\r
178 if (bottleneck > - i->tr_cap) bottleneck = - i -> tr_cap;
\r
181 /* 2. Augmenting */
\r
182 /* 2a - the source tree */
\r
183 *rev_cap_middle += bottleneck;
\r
184 *cap_middle -= bottleneck;
\r
185 for (i=s_start; ; )
\r
188 if (a == TERMINAL) break;
\r
192 a -> r_rev_cap += bottleneck;
\r
193 a -> r_cap -= bottleneck;
\r
196 /* add i to the adoption list */
\r
197 i -> parent = ORPHAN;
\r
198 np = nodeptr_block -> New();
\r
200 np -> next = orphan_first;
\r
203 i = NEIGHBOR_NODE_REV(i, a -> shift);
\r
207 a -> r_cap += bottleneck;
\r
208 a -> r_rev_cap -= bottleneck;
\r
211 /* add i to the adoption list */
\r
212 i -> parent = ORPHAN;
\r
213 np = nodeptr_block -> New();
\r
215 np -> next = orphan_first;
\r
218 i = NEIGHBOR_NODE(i, a -> shift);
\r
221 i -> tr_cap -= bottleneck;
\r
224 /* add i to the adoption list */
\r
225 i -> parent = ORPHAN;
\r
226 np = nodeptr_block -> New();
\r
228 np -> next = orphan_first;
\r
231 /* 2b - the sink tree */
\r
232 for (i=t_start; ; )
\r
235 if (a == TERMINAL) break;
\r
239 a -> r_cap += bottleneck;
\r
240 a -> r_rev_cap -= bottleneck;
\r
243 /* add i to the adoption list */
\r
244 i -> parent = ORPHAN;
\r
245 np = nodeptr_block -> New();
\r
247 np -> next = orphan_first;
\r
250 i = NEIGHBOR_NODE_REV(i, a -> shift);
\r
254 a -> r_rev_cap += bottleneck;
\r
255 a -> r_cap -= bottleneck;
\r
258 /* add i to the adoption list */
\r
259 i -> parent = ORPHAN;
\r
260 np = nodeptr_block -> New();
\r
262 np -> next = orphan_first;
\r
265 i = NEIGHBOR_NODE(i, a -> shift);
\r
268 i -> tr_cap += bottleneck;
\r
271 /* add i to the adoption list */
\r
272 i -> parent = ORPHAN;
\r
273 np = nodeptr_block -> New();
\r
275 np -> next = orphan_first;
\r
280 flow += bottleneck;
\r
283 /***********************************************************************/
\r
285 void Graph::process_source_orphan(node *i)
\r
288 arc_forward *a0_for, *a0_for_first, *a0_for_last;
\r
289 arc_reverse *a0_rev, *a0_rev_first, *a0_rev_last;
\r
290 arc_forward *a0_min = NULL, *a;
\r
292 int d, d_min = INFINITE_D;
\r
294 /* trying to find a new parent */
\r
295 a0_for_first = i -> first_out;
\r
296 if (IS_ODD(a0_for_first))
\r
298 a0_for_first = (arc_forward *) (((char *)a0_for_first) + 1);
\r
299 a0_for_last = (arc_forward *) ((a0_for_first ++) -> shift);
\r
301 else a0_for_last = (i + 1) -> first_out;
\r
302 a0_rev_first = i -> first_in;
\r
303 if (IS_ODD(a0_rev_first))
\r
305 a0_rev_first = (arc_reverse *) (((char *)a0_rev_first) + 1);
\r
306 a0_rev_last = (arc_reverse *) ((a0_rev_first ++) -> sister);
\r
308 else a0_rev_last = (i + 1) -> first_in;
\r
311 for (a0_for=a0_for_first; a0_for<a0_for_last; a0_for++)
\r
312 if (a0_for->r_rev_cap)
\r
314 j = NEIGHBOR_NODE(i, a0_for -> shift);
\r
315 if (!j->is_sink && (a=j->parent))
\r
317 /* checking the origin of j */
\r
334 if (a==ORPHAN) { d = INFINITE_D; break; }
\r
336 j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
\r
338 j = NEIGHBOR_NODE(j, a -> shift);
\r
340 if (d<INFINITE_D) /* j originates from the source - done */
\r
347 /* set marks along the path */
\r
348 for (j=NEIGHBOR_NODE(i, a0_for->shift); j->TS!=TIME; )
\r
354 j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
\r
356 j = NEIGHBOR_NODE(j, a -> shift);
\r
361 for (a0_rev=a0_rev_first; a0_rev<a0_rev_last; a0_rev++)
\r
363 a0_for = a0_rev -> sister;
\r
366 j = NEIGHBOR_NODE_REV(i, a0_for -> shift);
\r
367 if (!j->is_sink && (a=j->parent))
\r
369 /* checking the origin of j */
\r
386 if (a==ORPHAN) { d = INFINITE_D; break; }
\r
388 j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
\r
390 j = NEIGHBOR_NODE(j, a -> shift);
\r
392 if (d<INFINITE_D) /* j originates from the source - done */
\r
396 a0_min = MAKE_ODD(a0_for);
\r
399 /* set marks along the path */
\r
400 for (j=NEIGHBOR_NODE_REV(i,a0_for->shift); j->TS!=TIME; )
\r
406 j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
\r
408 j = NEIGHBOR_NODE(j, a -> shift);
\r
415 if (i->parent = a0_min)
\r
418 i -> DIST = d_min + 1;
\r
422 /* no parent is found */
\r
425 /* process neighbors */
\r
426 for (a0_for=a0_for_first; a0_for<a0_for_last; a0_for++)
\r
428 j = NEIGHBOR_NODE(i, a0_for -> shift);
\r
429 if (!j->is_sink && (a=j->parent))
\r
431 if (a0_for->r_rev_cap) set_active(j);
\r
432 if (a!=TERMINAL && a!=ORPHAN && IS_ODD(a) && NEIGHBOR_NODE_REV(j, MAKE_EVEN(a)->shift)==i)
\r
434 /* add j to the adoption list */
\r
435 j -> parent = ORPHAN;
\r
436 np = nodeptr_block -> New();
\r
438 if (orphan_last) orphan_last -> next = np;
\r
439 else orphan_first = np;
\r
445 for (a0_rev=a0_rev_first; a0_rev<a0_rev_last; a0_rev++)
\r
447 a0_for = a0_rev -> sister;
\r
448 j = NEIGHBOR_NODE_REV(i, a0_for -> shift);
\r
449 if (!j->is_sink && (a=j->parent))
\r
451 if (a0_for->r_cap) set_active(j);
\r
452 if (a!=TERMINAL && a!=ORPHAN && !IS_ODD(a) && NEIGHBOR_NODE(j, a->shift)==i)
\r
454 /* add j to the adoption list */
\r
455 j -> parent = ORPHAN;
\r
456 np = nodeptr_block -> New();
\r
458 if (orphan_last) orphan_last -> next = np;
\r
459 else orphan_first = np;
\r
468 void Graph::process_sink_orphan(node *i)
\r
471 arc_forward *a0_for, *a0_for_first, *a0_for_last;
\r
472 arc_reverse *a0_rev, *a0_rev_first, *a0_rev_last;
\r
473 arc_forward *a0_min = NULL, *a;
\r
475 int d, d_min = INFINITE_D;
\r
477 /* trying to find a new parent */
\r
478 a0_for_first = i -> first_out;
\r
479 if (IS_ODD(a0_for_first))
\r
481 a0_for_first = (arc_forward *) (((char *)a0_for_first) + 1);
\r
482 a0_for_last = (arc_forward *) ((a0_for_first ++) -> shift);
\r
484 else a0_for_last = (i + 1) -> first_out;
\r
485 a0_rev_first = i -> first_in;
\r
486 if (IS_ODD(a0_rev_first))
\r
488 a0_rev_first = (arc_reverse *) (((char *)a0_rev_first) + 1);
\r
489 a0_rev_last = (arc_reverse *) ((a0_rev_first ++) -> sister);
\r
491 else a0_rev_last = (i + 1) -> first_in;
\r
494 for (a0_for=a0_for_first; a0_for<a0_for_last; a0_for++)
\r
497 j = NEIGHBOR_NODE(i, a0_for -> shift);
\r
498 if (j->is_sink && (a=j->parent))
\r
500 /* checking the origin of j */
\r
517 if (a==ORPHAN) { d = INFINITE_D; break; }
\r
519 j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
\r
521 j = NEIGHBOR_NODE(j, a -> shift);
\r
523 if (d<INFINITE_D) /* j originates from the sink - done */
\r
530 /* set marks along the path */
\r
531 for (j=NEIGHBOR_NODE(i, a0_for->shift); j->TS!=TIME; )
\r
537 j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
\r
539 j = NEIGHBOR_NODE(j, a -> shift);
\r
544 for (a0_rev=a0_rev_first; a0_rev<a0_rev_last; a0_rev++)
\r
546 a0_for = a0_rev -> sister;
\r
547 if (a0_for->r_rev_cap)
\r
549 j = NEIGHBOR_NODE_REV(i, a0_for -> shift);
\r
550 if (j->is_sink && (a=j->parent))
\r
552 /* checking the origin of j */
\r
569 if (a==ORPHAN) { d = INFINITE_D; break; }
\r
571 j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
\r
573 j = NEIGHBOR_NODE(j, a -> shift);
\r
575 if (d<INFINITE_D) /* j originates from the sink - done */
\r
579 a0_min = MAKE_ODD(a0_for);
\r
582 /* set marks along the path */
\r
583 for (j=NEIGHBOR_NODE_REV(i,a0_for->shift); j->TS!=TIME; )
\r
589 j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
\r
591 j = NEIGHBOR_NODE(j, a -> shift);
\r
598 if (i->parent = a0_min)
\r
601 i -> DIST = d_min + 1;
\r
605 /* no parent is found */
\r
608 /* process neighbors */
\r
609 for (a0_for=a0_for_first; a0_for<a0_for_last; a0_for++)
\r
611 j = NEIGHBOR_NODE(i, a0_for -> shift);
\r
612 if (j->is_sink && (a=j->parent))
\r
614 if (a0_for->r_cap) set_active(j);
\r
615 if (a!=TERMINAL && a!=ORPHAN && IS_ODD(a) && NEIGHBOR_NODE_REV(j, MAKE_EVEN(a)->shift)==i)
\r
617 /* add j to the adoption list */
\r
618 j -> parent = ORPHAN;
\r
619 np = nodeptr_block -> New();
\r
621 if (orphan_last) orphan_last -> next = np;
\r
622 else orphan_first = np;
\r
628 for (a0_rev=a0_rev_first; a0_rev<a0_rev_last; a0_rev++)
\r
630 a0_for = a0_rev -> sister;
\r
631 j = NEIGHBOR_NODE_REV(i, a0_for -> shift);
\r
632 if (j->is_sink && (a=j->parent))
\r
634 if (a0_for->r_rev_cap) set_active(j);
\r
635 if (a!=TERMINAL && a!=ORPHAN && !IS_ODD(a) && NEIGHBOR_NODE(j, a->shift)==i)
\r
637 /* add j to the adoption list */
\r
638 j -> parent = ORPHAN;
\r
639 np = nodeptr_block -> New();
\r
641 if (orphan_last) orphan_last -> next = np;
\r
642 else orphan_first = np;
\r
651 /***********************************************************************/
\r
653 Graph::flowtype Graph::maxflow()
\r
655 node *i, *j, *current_node = NULL, *s_start, *t_start;
\r
656 captype *cap_middle, *rev_cap_middle;
\r
657 arc_forward *a_for, *a_for_first, *a_for_last;
\r
658 arc_reverse *a_rev, *a_rev_first, *a_rev_last;
\r
659 nodeptr *np, *np_next;
\r
663 nodeptr_block = new DBlock<nodeptr>(NODEPTR_BLOCK_SIZE, error_function);
\r
667 if (i=current_node)
\r
669 i -> next = NULL; /* remove active flag */
\r
670 if (!i->parent) i = NULL;
\r
674 if (!(i = next_active())) break;
\r
680 a_for_first = i -> first_out;
\r
681 if (IS_ODD(a_for_first))
\r
683 a_for_first = (arc_forward *) (((char *)a_for_first) + 1);
\r
684 a_for_last = (arc_forward *) ((a_for_first ++) -> shift);
\r
686 else a_for_last = (i + 1) -> first_out;
\r
687 a_rev_first = i -> first_in;
\r
688 if (IS_ODD(a_rev_first))
\r
690 a_rev_first = (arc_reverse *) (((char *)a_rev_first) + 1);
\r
691 a_rev_last = (arc_reverse *) ((a_rev_first ++) -> sister);
\r
693 else a_rev_last = (i + 1) -> first_in;
\r
697 /* grow source tree */
\r
698 for (a_for=a_for_first; a_for<a_for_last; a_for++)
\r
701 j = NEIGHBOR_NODE(i, a_for -> shift);
\r
705 j -> parent = MAKE_ODD(a_for);
\r
707 j -> DIST = i -> DIST + 1;
\r
710 else if (j->is_sink)
\r
714 cap_middle = & ( a_for -> r_cap );
\r
715 rev_cap_middle = & ( a_for -> r_rev_cap );
\r
718 else if (j->TS <= i->TS &&
\r
721 /* heuristic - trying to make the distance from j to the source shorter */
\r
722 j -> parent = MAKE_ODD(a_for);
\r
724 j -> DIST = i -> DIST + 1;
\r
728 for (a_rev=a_rev_first; a_rev<a_rev_last; a_rev++)
\r
730 a_for = a_rev -> sister;
\r
731 if (a_for->r_rev_cap)
\r
733 j = NEIGHBOR_NODE_REV(i, a_for -> shift);
\r
737 j -> parent = a_for;
\r
739 j -> DIST = i -> DIST + 1;
\r
742 else if (j->is_sink)
\r
746 cap_middle = & ( a_for -> r_rev_cap );
\r
747 rev_cap_middle = & ( a_for -> r_cap );
\r
750 else if (j->TS <= i->TS &&
\r
753 /* heuristic - trying to make the distance from j to the source shorter */
\r
754 j -> parent = a_for;
\r
756 j -> DIST = i -> DIST + 1;
\r
763 /* grow sink tree */
\r
764 for (a_for=a_for_first; a_for<a_for_last; a_for++)
\r
765 if (a_for->r_rev_cap)
\r
767 j = NEIGHBOR_NODE(i, a_for -> shift);
\r
771 j -> parent = MAKE_ODD(a_for);
\r
773 j -> DIST = i -> DIST + 1;
\r
776 else if (!j->is_sink)
\r
780 cap_middle = & ( a_for -> r_rev_cap );
\r
781 rev_cap_middle = & ( a_for -> r_cap );
\r
784 else if (j->TS <= i->TS &&
\r
787 /* heuristic - trying to make the distance from j to the sink shorter */
\r
788 j -> parent = MAKE_ODD(a_for);
\r
790 j -> DIST = i -> DIST + 1;
\r
793 for (a_rev=a_rev_first; a_rev<a_rev_last; a_rev++)
\r
795 a_for = a_rev -> sister;
\r
798 j = NEIGHBOR_NODE_REV(i, a_for -> shift);
\r
802 j -> parent = a_for;
\r
804 j -> DIST = i -> DIST + 1;
\r
807 else if (!j->is_sink)
\r
811 cap_middle = & ( a_for -> r_cap );
\r
812 rev_cap_middle = & ( a_for -> r_rev_cap );
\r
815 else if (j->TS <= i->TS &&
\r
818 /* heuristic - trying to make the distance from j to the sink shorter */
\r
819 j -> parent = a_for;
\r
821 j -> DIST = i -> DIST + 1;
\r
831 i -> next = i; /* set active flag */
\r
835 augment(s_start, t_start, cap_middle, rev_cap_middle);
\r
836 /* augmentation end */
\r
839 while (np=orphan_first)
\r
841 np_next = np -> next;
\r
844 while (np=orphan_first)
\r
846 orphan_first = np -> next;
\r
848 nodeptr_block -> Delete(np);
\r
849 if (!orphan_first) orphan_last = NULL;
\r
850 if (i->is_sink) process_sink_orphan(i);
\r
851 else process_source_orphan(i);
\r
854 orphan_first = np_next;
\r
858 else current_node = NULL;
\r
861 delete nodeptr_block;
\r
866 /***********************************************************************/
\r
868 Graph::termtype Graph::what_segment(node_id i)
\r
870 if (((node*)i)->parent && !((node*)i)->is_sink) return SOURCE;
\r