Bipartite Weighted Assignment
      What is an Assignment in a Bipartite Graph?
      A graph is bipartite if it has two kinds of nodes and the edges 
        are only allowed between nodes of different kind. A matching in a bipartite 
        graph therefore assigns nodes of one kind to nodes of the other kind. 
        Matchings in bipartite graphs can be computed more efficiently than matchings 
        in general (=non-bipartite) graphs.  
      A matching in a graph G=(V,E) is a subset M of the edges E such 
        that no two edges in M share a common end node. An assignment in 
        a bipartite graph is a matching M such that each node of the graph has 
        an incident edge in M. If the edges of the graph have an associated weight, 
        then a  maximum (minimum) weighted assignment is an assignment 
        such that the sum of the weights of the edges is maximum (minimum).  
      Intuition: Suppose we have a set of workers and a set of machines. 
        These are the two kinds of nodes in our bipartite graph. We know which 
        worker can handle which machines. This defines the edges of the bipartite 
        graph. Additionally, we know the profit of assigning worker w 
        to machine m. This defines the edge weight. Our task in the 
        maximum weighted assignment problem is to assign exactly one worker to 
        each machine in such a way that the total profit is maximum. 
       Proof of Optimality of the Resulting Matching
      All functions for computing weighted matchings in bipartite graphs provide 
        a proof of optimality in the form of a potential function pot 
        for the nodes of the graph. The potential function corresponds to the 
        node cover in Maximum Cardinality 
        Matching in Bipartite Graphs. Details can be found in the LEDA 
        Book. 
      The Number Type for the Edge Weights
      All functions in this section are template functions. The template parameter 
        NT can be instantiated with any number 
        type. Additionally, there are preinstantiated versions for int 
        and double. The names of the template functions have suffix 
        _T and the functions without suffix _T are the 
        preinstantiated versions 
       The reason why we did not restrict our algorithms to int 
        and double is that the number types int, float, 
        and double provided by C++ are only crude approximations 
        of the mathematical counterparts: ints can overflow, the 
        arithmetic for floats and doubles incurs rounding 
        errors. The functions in this section only perform correctly if all arithmetic 
        is performed without rounding errors. 
       LEDA Functions for Bipartite Weighted Assignment
      Remark: In the following we describe only the functions for maximum 
        weighted assignment. The functions for minimum weighted assignment can 
        be used in exactly the same way. You only have to replace MAX by MIN in 
        the function names. 
      MAX_WEIGHT_ASSIGNMENT_T() computes a maximum weighted 
        assignment in a bipartite graph if one exists. MAX_WEIGHT_ASSIGNMENT_T() 
        is a template function. The template parameter NT can be 
        instantiated with any number type.  
      CHECK_MAX_WEIGHT_ASSIGNMENT_T() checks if the result 
        of MAX_WEIGHT_ASSIGNMENT_T(), a list<edge> 
        M and a node_array<NT> 
        pot,  are a maximum weighted assignment and a corresponding potential 
        function of the bipartite graph G.  
      Example 
        of MAX_WEIGHT_ASSIGNMENT_T() and CHECK_MAX_WEIGHT_ASSIGNMENT_T() 
        
      MAX_WEIGHT_ASSIGNMENT() is the name of the preinstantiated 
        versions of MAX_WEIGHT_ASSIGNMENT_T(). There is one function 
        for edge weights of type int and one for double. 
      CHECK_MAX_WEIGHT_ASSIGNMENT() checks if the result 
        of MAX_WEIGHT_ASSIGNMENT(), a list<edge> 
        M and a node_array<int> 
        pot  , respectively node_array<double> 
        pot,  are a maximum weighted assignment and a corresponding potential 
        function of the bipartite graph G. 
      Important Notice: MAX_WEIGHT_ASSIGNMENT() only performs 
        correctly if all arithmetic is performed without rounding errors and without 
        overflows. If you are not sure about this, you should use MAX_WEIGHT_ASSIGNMENT_T() 
        with one of the LEDA number types. MAX_WEIGHT_ASSIGNMENT() 
        for int issues a warning if incorrect results are possible. 
        MAX_WEIGHT_ASSIGNMENT() for double computes 
        a maximum weighted assignment for modified edge weights in order to avoid 
        internal arithmetic problems. Details can be found in the LEDA Book. Using 
        the following function you can do the weight modification explicitely. 
      MWA_SCALE_WEIGHTS() modifies the edge weights for 
        MAX_WEIGHT_ASSIGNMENT() with double in order 
        to avoid internal arithmetic problems. The function returns false 
        if it changed some edge capacities and true otherwise. 
      Example 
        of MAX_WEIGHT_ASSIGNMENT(),CHECK_MAX_WEIGHT_ASSIGNMENT(),MWA_SCALE_WEIGHTS() 
        
      Running times
      For a bipartite graph G=(V,E), the running times of of computing 
      a maximum (minimum) weighted assignment is O(|V|*(|E|+|V|log|V|)). The checking 
      and scaling functions are linear in the size of the graph. 
      Tips
      
        - Use 
MAX_WEIGHT_ASSIGNMENT_T() to compute a maximum weighted 
          assignment in a bipartite graph. 
        - If you are determined to use 
MAX_WEIGHT_ASSIGNMENT()be 
          aware of the arithmetic problems that may arise. In case of double 
          edge weights use MWA_SCALE_WEIGHTS() to modify the edge 
          weights explicitely. 
        - Use 
CHECK_MAX_WEIGHT_ASSIGNMENT_T() and CHECK_MAX_WEIGHT_ASSIGNMENT() 
          to ensure the correctness of your result. Checking the result 
          is much easier than computing a maximum weighted assignment in a bipartite 
          graph. Therefore, these are less complicated and less error prone. Moreover, 
          checking is only linear in the size of the graph. So, the overhead is 
          quite small.  
       
       |