+ e = &_edges[k];
+ if(e->occupied) { e->invert(); }
+ }
+}
+
+int MTPGraph::retrieve_one_path(Edge *e, Path *path) {
+ Edge *f, *next = 0;
+ int l = 0, nb_occupied_next;
+
+ if(path) {
+ path->nodes[l++] = int(e->origin_vertex - _vertices);
+ path->length = e->length;
+ } else l++;
+
+ while(e->terminal_vertex != _sink) {
+ if(path) {
+ path->nodes[l++] = int(e->terminal_vertex - _vertices);
+ path->length += e->length;
+ } else l++;
+
+ nb_occupied_next = 0;
+ for(f = e->terminal_vertex->leaving_edge_list_root; f; f = f->next_leaving_edge) {
+ if(f->occupied) { nb_occupied_next++; next = f; }
+ }
+
+#ifdef DEBUG
+ if(nb_occupied_next == 0) {
+ cerr << __FILE__ << ": retrieve_one_path: Non-sink end point." << endl;
+ abort();
+ }
+
+ else if(nb_occupied_next > 1) {
+ cerr << __FILE__ << ": retrieve_one_path: Non node-disjoint paths." << endl;
+ abort();
+ }
+#endif
+
+ e = next;
+ }
+
+ if(path) {
+ path->nodes[l++] = int(e->terminal_vertex - _vertices);
+ path->length += e->length;
+ } else l++;
+
+ return l;
+}
+
+//////////////////////////////////////////////////////////////////////
+
+void MTPGraph::compute_dp_ordering() {
+ Vertex *v;
+ Edge *e;
+ int ntv;
+
+ // This method orders the nodes by putting first the ones with no
+ // predecessors, then going on adding nodes whose predecessors have
+ // all been already added. Computing the distances from the source
+ // by visiting nodes in that order is equivalent to DP.
+
+ int *nb_predecessors = new int[_nb_vertices];
+
+ Vertex **already_processed = _dp_order, **front = _dp_order, **new_front = _dp_order;
+
+ for(int k = 0; k < _nb_vertices; k++) {
+ nb_predecessors[k] = 0;
+ }
+
+ for(int k = 0; k < _nb_vertices; k++) {
+ v = &_vertices[k];
+ for(e = v->leaving_edge_list_root; e; e = e->next_leaving_edge) {
+ ntv = int(e->terminal_vertex - _vertices);
+ nb_predecessors[ntv]++;
+ }
+ }
+
+ for(int k = 0; k < _nb_vertices; k++) {
+ if(nb_predecessors[k] == 0) {
+ *(front++) = _vertices + k;
+ }
+ }
+
+ while(already_processed < front) {
+ // Here, nodes before already_processed can be ignored, nodes
+ // before front were set to 0 predecessors during the previous
+ // iteration. During this new iteration, we have to visit the
+ // successors of these ones only, since they are the only ones
+ // potentially having now predecessors anymore.
+ new_front = front;
+ while(already_processed < front) {
+ v = *(already_processed++);
+ for(e = v->leaving_edge_list_root; e; e = e->next_leaving_edge) {
+ ntv = int(e->terminal_vertex - _vertices);
+ nb_predecessors[ntv]--;
+ ASSERT(nb_predecessors[ntv] >= 0);
+ if(nb_predecessors[ntv] == 0) {
+ *(new_front++) = e->terminal_vertex;
+ }
+ }
+ }
+ front = new_front;