Some comments and minor additions to the AdvancedController.
     2  * src/lemon/list_graph.h - Part of LEMON, a generic C++ optimization library
 
     4  * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 
     5  * (Egervary Combinatorial Optimization Research Group, EGRES).
 
     7  * Permission to use, modify and distribute this software is granted
 
     8  * provided that this copyright notice appears in all copies. For
 
     9  * precise terms see the accompanying LICENSE file.
 
    11  * This software is provided "AS IS" with no warranty of any kind,
 
    12  * express or implied, and with no claim as to its suitability for any
 
    17 #ifndef LEMON_LIST_GRAPH_H
 
    18 #define LEMON_LIST_GRAPH_H
 
    22 ///\brief ListGraph, SymListGraph, NodeSet and EdgeSet classes.
 
    24 #include <lemon/erasable_graph_extender.h>
 
    25 #include <lemon/clearable_graph_extender.h>
 
    26 #include <lemon/extendable_graph_extender.h>
 
    28 #include <lemon/iterable_graph_extender.h>
 
    30 #include <lemon/alteration_observer_registry.h>
 
    32 #include <lemon/default_map.h>
 
    41       int first_in,first_out;
 
    47       int prev_in, prev_out;
 
    48       int next_in, next_out;
 
    51     std::vector<NodeT> nodes;
 
    57     std::vector<EdgeT> edges;
 
    63     typedef ListGraphBase Graph;
 
    66       friend class ListGraphBase;
 
    70       Node(int pid) { id = pid;}
 
    74       Node (Invalid) { id = -1; }
 
    75       bool operator==(const Node& node) const {return id == node.id;}
 
    76       bool operator!=(const Node& node) const {return id != node.id;}
 
    77       bool operator<(const Node& node) const {return id < node.id;}
 
    81       friend class ListGraphBase;
 
    85       Edge(int pid) { id = pid;}
 
    89       Edge (Invalid) { id = -1; }
 
    90       bool operator==(const Edge& edge) const {return id == edge.id;}
 
    91       bool operator!=(const Edge& edge) const {return id != edge.id;}
 
    92       bool operator<(const Edge& edge) const {return id < edge.id;}
 
    98       : nodes(), first_node(-1),
 
    99 	first_free_node(-1), edges(), first_free_edge(-1) {}
 
   106     int maxId(Node = INVALID) const { return nodes.size()-1; } 
 
   112     int maxId(Edge = INVALID) const { return edges.size()-1; }
 
   114     Node source(Edge e) const { return edges[e.id].source; }
 
   115     Node target(Edge e) const { return edges[e.id].target; }
 
   118     void first(Node& node) const { 
 
   119       node.id = first_node;
 
   122     void next(Node& node) const {
 
   123       node.id = nodes[node.id].next;
 
   127     void first(Edge& e) const { 
 
   130 	  n!=-1 && nodes[n].first_in == -1; 
 
   132       e.id = (n == -1) ? -1 : nodes[n].first_in;
 
   135     void next(Edge& edge) const {
 
   136       if (edges[edge.id].next_in != -1) {
 
   137 	edge.id = edges[edge.id].next_in;
 
   140 	for(n = nodes[edges[edge.id].target].next;
 
   141 	  n!=-1 && nodes[n].first_in == -1; 
 
   143 	edge.id = (n == -1) ? -1 : nodes[n].first_in;
 
   147     void firstOut(Edge &e, const Node& v) const {
 
   148       e.id = nodes[v.id].first_out;
 
   150     void nextOut(Edge &e) const {
 
   151       e.id=edges[e.id].next_out;
 
   154     void firstIn(Edge &e, const Node& v) const {
 
   155       e.id = nodes[v.id].first_in;
 
   157     void nextIn(Edge &e) const {
 
   158       e.id=edges[e.id].next_in;
 
   162     static int id(Node v) { return v.id; }
 
   163     static int id(Edge e) { return e.id; }
 
   165     /// Adds a new node to the graph.
 
   167     /// \warning It adds the new node to the front of the list.
 
   168     /// (i.e. the lastly added node becomes the first.)
 
   172       if(first_free_node==-1) {
 
   174 	nodes.push_back(NodeT());
 
   177 	first_free_node = nodes[n].next;
 
   180       nodes[n].next = first_node;
 
   181       if(first_node != -1) nodes[first_node].prev = n;
 
   185       nodes[n].first_in = nodes[n].first_out = -1;
 
   190     Edge addEdge(Node u, Node v) {
 
   193       if (first_free_edge == -1) {
 
   195 	edges.push_back(EdgeT());
 
   198 	first_free_edge = edges[n].next_in;
 
   201       edges[n].source = u.id; 
 
   202       edges[n].target = v.id;
 
   204       edges[n].next_out = nodes[u.id].first_out;
 
   205       if(nodes[u.id].first_out != -1) {
 
   206 	edges[nodes[u.id].first_out].prev_out = n;
 
   209       edges[n].next_in = nodes[v.id].first_in;
 
   210       if(nodes[v.id].first_in != -1) {
 
   211 	edges[nodes[v.id].first_in].prev_in = n;
 
   214       edges[n].prev_in = edges[n].prev_out = -1;
 
   216       nodes[u.id].first_out = nodes[v.id].first_in = n;
 
   221     void erase(const Node& node) {
 
   224       if(nodes[n].next != -1) {
 
   225 	nodes[nodes[n].next].prev = nodes[n].prev;
 
   228       if(nodes[n].prev != -1) {
 
   229 	nodes[nodes[n].prev].next = nodes[n].next;
 
   231 	first_node = nodes[n].next;
 
   234       nodes[n].next = first_free_node;
 
   239     void erase(const Edge& edge) {
 
   242       if(edges[n].next_in!=-1) {
 
   243 	edges[edges[n].next_in].prev_in = edges[n].prev_in;
 
   246       if(edges[n].prev_in!=-1) {
 
   247 	edges[edges[n].prev_in].next_in = edges[n].next_in;
 
   249 	nodes[edges[n].target].first_in = edges[n].next_in;
 
   253       if(edges[n].next_out!=-1) {
 
   254 	edges[edges[n].next_out].prev_out = edges[n].prev_out;
 
   257       if(edges[n].prev_out!=-1) {
 
   258 	edges[edges[n].prev_out].next_out = edges[n].next_out;
 
   260 	nodes[edges[n].source].first_out = edges[n].next_out;
 
   263       edges[n].next_in = first_free_edge;
 
   271       first_node = first_free_node = first_free_edge = -1;
 
   275     void _moveTarget(Edge e, Node n) 
 
   277       if(edges[e.id].next_in != -1)
 
   278 	edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
 
   279       if(edges[e.id].prev_in != -1)
 
   280 	edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
 
   281       else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
 
   282       edges[e.id].target = n.id;
 
   283       edges[e.id].prev_in = -1;
 
   284       edges[e.id].next_in = nodes[n.id].first_in;
 
   285       nodes[n.id].first_in = e.id;
 
   287     void _moveSource(Edge e, Node n) 
 
   289       if(edges[e.id].next_out != -1)
 
   290 	edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
 
   291       if(edges[e.id].prev_out != -1)
 
   292 	edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
 
   293       else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
 
   294       edges[e.id].source = n.id;
 
   295       edges[e.id].prev_out = -1;
 
   296       edges[e.id].next_out = nodes[n.id].first_out;
 
   297       nodes[n.id].first_out = e.id;
 
   302   typedef AlterableGraphExtender<ListGraphBase> AlterableListGraphBase;
 
   303   typedef IterableGraphExtender<AlterableListGraphBase> IterableListGraphBase;
 
   304   typedef DefaultMappableGraphExtender<IterableListGraphBase> MappableListGraphBase;
 
   305   typedef ExtendableGraphExtender<MappableListGraphBase> ExtendableListGraphBase;
 
   306   typedef ClearableGraphExtender<ExtendableListGraphBase> ClearableListGraphBase;
 
   307   typedef ErasableGraphExtender<ClearableListGraphBase> ErasableListGraphBase;
 
   309 /// \addtogroup graphs
 
   312   ///A list graph class.
 
   314   ///This is a simple and fast erasable graph implementation.
 
   316   ///It conforms to the
 
   317   ///\ref concept::ErasableGraph "ErasableGraph" concept.
 
   318   ///\sa concept::ErasableGraph.
 
   320   class ListGraph : public ErasableListGraphBase 
 
   323     /// Moves the target of \c e to \c n
 
   325     /// Moves the target of \c e to \c n
 
   327     void moveTarget(Edge e, Node n) { _moveTarget(e,n); }
 
   328     /// Moves the source of \c e to \c n
 
   330     /// Moves the source of \c e to \c n
 
   332     void moveSource(Edge e, Node n) { _moveSource(e,n); }
 
   334     ///Using this it possible to avoid the superfluous memory allocation.
 
   335     ///\todo more docs...
 
   336     void reserveEdge(int n) { edges.reserve(n); };