# HG changeset patch
# User deba
# Date 1174578050 0
# Node ID 21eb3ccdc3dfa28b28a27d7a3a256743874d2d18
# Parent 086fc76d591d1a6638e97a6c835fe949c41bb326
Right dimacs format for min cost flows
Bug fixes in tolerance and min_mean_cycle
diff -r 086fc76d591d -r 21eb3ccdc3df demo/dim_to_dot.cc
--- a/demo/dim_to_dot.cc Thu Mar 22 06:36:50 2007 +0000
+++ b/demo/dim_to_dot.cc Thu Mar 22 15:40:50 2007 +0000
@@ -17,17 +17,15 @@
*/
///\file
-///\brief Dim (Dimacs) to Dot (Graphviz) converter
+///\brief Dim (DIMACS) to Dot (Graphviz) converter
///
-/// This program can convert the dimacs format to graphviz dot format.
+/// This program can convert the DIMACS format to Graphviz format.
///
-/// Use a DIMACS max flow file as stdin.
+/// dim_to_dot dimacs_max_flow_file > dot_output_file
///
-/// dim_to_dot < dimacs_max_flow_file > dot_output_file
-///
-/// This program makes a dot file from a dimacs max flow file.
-/// This program can be an aid in making up to date visualized documantation
-/// of demo programs.
+/// This program makes a dot file from a DIMACS max flow file.
+/// This program can be an aid in making up to date visualized
+/// documantation of demo programs.
///
/// \include dim_to_dot.cc
@@ -46,12 +44,11 @@
{
if(argc<2)
{
- std::cerr << "USAGE: sub_graph_adaptor_demo input_file.dim" << std::endl;
+ std::cerr << "USAGE: dim_to_dot input_file.dim" << std::endl;
std::cerr << "The file 'input_file.dim' has to contain a max flow instance in DIMACS format (e.g. sub_graph_adaptor_demo.dim is such a file)." << std::endl;
return 0;
}
-
//input stream to read the graph from
std::ifstream is(argv[1]);
diff -r 086fc76d591d -r 21eb3ccdc3df lemon/dimacs.h
--- a/lemon/dimacs.h Thu Mar 22 06:36:50 2007 +0000
+++ b/lemon/dimacs.h Thu Mar 22 15:40:50 2007 +0000
@@ -27,11 +27,10 @@
/// \ingroup dimacs_group
/// \file
-/// \brief Dimacs file format reader.
+/// \brief DIMACS file format reader.
namespace lemon {
- ///
///@defgroup dimacs_group DIMACS format
///\brief Read and write files in DIMACS format
///
@@ -41,114 +40,147 @@
/// \addtogroup dimacs_group
/// @{
+
+ /// DIMACS min cost flow reader function.
+ ///
+ /// This function reads a min cost flow instance from DIMACS format,
+ /// i.e. from DIMACS files having a line starting with
+ /// \code
+ /// p min
+ /// \endcode
+ /// At the beginning \c g is cleared by \c g.clear(). The supply
+ /// amount of the nodes are written to \c supply (signed). The
+ /// lower bounds, capacities and costs of the edges are written to
+ /// \c lower, \c capacity and \c cost.
+ ///
+ /// \author Marton Makai and Peter Kovacs
+ template
+ void readDimacs( std::istream& is,
+ Graph &g,
+ SupplyMap& supply,
+ CapacityMap& lower,
+ CapacityMap& capacity,
+ CostMap& cost )
+ {
+ g.clear();
+ std::vector nodes;
+ typename Graph::Edge e;
+ std::string problem, str;
+ char c;
+ int n, m;
+ int i, j;
+ typename SupplyMap::Value sup;
+ typename CapacityMap::Value low;
+ typename CapacityMap::Value cap;
+ typename CostMap::Value co;
+ while (is >> c) {
+ switch (c) {
+ case 'c': // comment line
+ getline(is, str);
+ break;
+ case 'p': // problem definition line
+ is >> problem >> n >> m;
+ getline(is, str);
+ if (problem != "min") return;
+ nodes.resize(n + 1);
+ for (int k = 1; k <= n; ++k) {
+ nodes[k] = g.addNode();
+ supply[nodes[k]] = 0;
+ }
+ break;
+ case 'n': // node definition line
+ is >> i >> sup;
+ getline(is, str);
+ supply.set(nodes[i], sup);
+ break;
+ case 'a': // edge (arc) definition line
+ is >> i >> j >> low >> cap >> co;
+ getline(is, str);
+ e = g.addEdge(nodes[i], nodes[j]);
+ lower.set(e, low);
+ if (cap >= 0)
+ capacity.set(e, cap);
+ else
+ capacity.set(e, -1);
+ cost.set(e, co);
+ break;
+ }
+ }
+ }
- /// Dimacs min cost flow reader function.
-
- /// This function reads a min cost flow instance from dimacs format,
- /// i.e. from dimacs files having a line starting with
- ///\code
- /// p "min"
- ///\endcode
- /// At the beginning \c g is cleared by \c g.clear(). The edge
- /// capacities are written to \c capacity, \c s and \c t are set to
- /// the source and the target nodes resp. and the cost of the edges
- /// are written to \c cost.
+ /// DIMACS max flow reader function.
+ ///
+ /// This function reads a max flow instance from DIMACS format,
+ /// i.e. from DIMACS files having a line starting with
+ /// \code
+ /// p max
+ /// \endcode
+ /// At the beginning \c g is cleared by \c g.clear(). The edge
+ /// capacities are written to \c capacity and \c s and \c t are
+ /// set to the source and the target nodes.
///
/// \author Marton Makai
- template
+ template
void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity,
- typename Graph::Node &s, typename Graph::Node &t,
- CostMap& cost) {
+ typename Graph::Node &s, typename Graph::Node &t) {
g.clear();
+ std::vector nodes;
+ typename Graph::Edge e;
+ std::string problem;
+ char c, d;
+ int n, m;
+ int i, j;
typename CapacityMap::Value _cap;
- typename CostMap::Value _cost;
- char d;
- std::string problem;
- char c;
- int i, j;
std::string str;
- int n, m;
- typename Graph::Edge e;
- std::vector nodes;
- while (is>>c) {
+ while (is >> c) {
switch (c) {
- case 'c': //comment
+ case 'c': // comment line
getline(is, str);
break;
- case 'p': //problem definition
+ case 'p': // problem definition line
is >> problem >> n >> m;
getline(is, str);
- nodes.resize(n+1);
- for (int k=1; k<=n; ++k) nodes[k]=g.addNode();
+ nodes.resize(n + 1);
+ for (int k = 1; k <= n; ++k)
+ nodes[k] = g.addNode();
break;
- case 'n': //node definition
- if (problem=="sp") { //shortest path problem
+ case 'n': // node definition line
+ if (problem == "sp") { // shortest path problem
is >> i;
getline(is, str);
- s=nodes[i];
+ s = nodes[i];
}
- if (problem=="max" || problem=="min") { //((max) or (min cost)) flow problem
+ if (problem == "max") { // max flow problem
is >> i >> d;
getline(is, str);
- if (d=='s') s=nodes[i];
- if (d=='t') t=nodes[i];
+ if (d == 's') s = nodes[i];
+ if (d == 't') t = nodes[i];
}
break;
- case 'a':
- if ( problem == "max" || problem == "sp") {
+ case 'a': // edge (arc) definition line
+ if (problem == "max" || problem == "sp") {
is >> i >> j >> _cap;
getline(is, str);
- e=g.addEdge(nodes[i], nodes[j]);
- //capacity.update();
+ e = g.addEdge(nodes[i], nodes[j]);
capacity.set(e, _cap);
} else {
- if ( problem == "min" ) {
- is >> i >> j >> _cap >> _cost;
- getline(is, str);
- e=g.addEdge(nodes[i], nodes[j]);
- //capacity.update();
- capacity.set(e, _cap);
- //cost.update();
- cost.set(e, _cost);
- } else {
- is >> i >> j;
- getline(is, str);
- g.addEdge(nodes[i], nodes[j]);
- }
+ is >> i >> j;
+ getline(is, str);
+ g.addEdge(nodes[i], nodes[j]);
}
break;
}
}
}
-
- /// Dimacs max flow reader function.
-
- /// This function reads a max flow instance from dimacs format,
- /// i.e. from dimacs files having a line starting with
- ///\code
- /// p "max"
- ///\endcode
- ///At the beginning \c g is cleared by \c g.clear(). The
- /// edge capacities are written to \c capacity and \c s and \c t are
- /// set to the source and the target nodes.
+ /// DIMACS shortest path reader function.
///
- /// \author Marton Makai
- template
- void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity,
- typename Graph::Node &s, typename Graph::Node &t) {
- NullMap n;
- readDimacs(is, g, capacity, s, t, n);
- }
-
-
- /// Dimacs shortest path reader function.
-
- /// This function reads a shortest path instance from dimacs format,
- /// i.e. from dimacs files having a line starting with
- ///\code
- /// p "sp"
- ///\endcode
+ /// This function reads a shortest path instance from DIMACS format,
+ /// i.e. from DIMACS files having a line starting with
+ /// \code
+ /// p sp
+ /// \endcode
/// At the beginning \c g is cleared by \c g.clear(). The edge
/// capacities are written to \c capacity and \c s is set to the
/// source node.
@@ -157,70 +189,67 @@
template
void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity,
typename Graph::Node &s) {
- NullMap n;
- readDimacs(is, g, capacity, s, s, n);
+ readDimacs(is, g, capacity, s, s);
}
-
- /// Dimacs capacitated graph reader function.
-
+ /// DIMACS capacitated graph reader function.
+ ///
/// This function reads an edge capacitated graph instance from
- /// dimacs format. At the beginning \c g is cleared by \c g.clear()
+ /// DIMACS format. At the beginning \c g is cleared by \c g.clear()
/// and the edge capacities are written to \c capacity.
///
/// \author Marton Makai
template
void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity) {
typename Graph::Node u;
- NullMap n;
- readDimacs(is, g, capacity, u, u, n);
+ readDimacs(is, g, capacity, u, u);
}
-
- /// Dimacs plain graph reader function.
-
+ /// DIMACS plain graph reader function.
+ ///
/// This function reads a graph without any designated nodes and
- /// maps from dimacs format, i.e. from dimacs files having a line
+ /// maps from DIMACS format, i.e. from DIMACS files having a line
/// starting with
- ///\code
- /// p "mat"
- ///\endcode
- /// At the beginning \c g is cleared
- /// by \c g.clear().
+ /// \code
+ /// p mat
+ /// \endcode
+ /// At the beginning \c g is cleared by \c g.clear().
///
/// \author Marton Makai
template
void readDimacs(std::istream& is, Graph &g) {
typename Graph::Node u;
NullMap n;
- readDimacs(is, g, n, u, u, n);
+ readDimacs(is, g, n, u, u);
}
-
-
-
- /// write matching problem
+ /// DIMACS plain graph writer function.
+ ///
+ /// This function writes a graph without any designated nodes and
+ /// maps into DIMACS format, i.e. into DIMACS file having a line
+ /// starting with
+ /// \code
+ /// p mat
+ /// \endcode
+ ///
+ /// \author Marton Makai
template
void writeDimacs(std::ostream& os, const Graph &g) {
typedef typename Graph::NodeIt NodeIt;
typedef typename Graph::EdgeIt EdgeIt;
+ os << "c matching problem" << std::endl;
+ os << "p mat " << g.nodeNum() << " " << g.edgeNum() << std::endl;
+
typename Graph::template NodeMap nodes(g);
-
- os << "c matching problem" << std::endl;
-
- int i=1;
- for(NodeIt v(g); v!=INVALID; ++v) {
+ int i = 1;
+ for(NodeIt v(g); v != INVALID; ++v) {
nodes.set(v, i);
++i;
}
-
- os << "p mat " << g.nodeNum() << " " << g.edgeNum() << std::endl;
-
- for(EdgeIt e(g); e!=INVALID; ++e) {
+ for(EdgeIt e(g); e != INVALID; ++e) {
os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)] << std::endl;
}
-
}
/// @}
diff -r 086fc76d591d -r 21eb3ccdc3df lemon/min_mean_cycle.h
--- a/lemon/min_mean_cycle.h Thu Mar 22 06:36:50 2007 +0000
+++ b/lemon/min_mean_cycle.h Thu Mar 22 15:40:50 2007 +0000
@@ -33,11 +33,11 @@
/// \addtogroup min_cost_flow
/// @{
- /// \brief Implementation of Karp's algorithm for finding a
- /// minimum mean cycle.
+ /// \brief Implementation of Karp's algorithm for finding a
+ /// minimum mean (directed) cycle.
///
- /// The \ref lemon::MinMeanCycle "MinMeanCycle" implements Karp's
- /// algorithm for finding a minimum mean cycle.
+ /// The \ref lemon::MinMeanCycle "MinMeanCycle" implements Karp's
+ /// algorithm for finding a minimum mean (directed) cycle.
///
/// \param Graph The directed graph type the algorithm runs on.
/// \param LengthMap The type of the length (cost) map.
@@ -57,11 +57,10 @@
typedef typename Graph::NodeIt NodeIt;
typedef typename Graph::Edge Edge;
typedef typename Graph::EdgeIt EdgeIt;
- typedef typename Graph::InEdgeIt InEdgeIt;
typedef typename Graph::OutEdgeIt OutEdgeIt;
typedef typename LengthMap::Value Length;
-
+
typedef typename Graph::template NodeMap IntNodeMap;
typedef typename Graph::template NodeMap PredNodeMap;
typedef Path Path;
@@ -69,22 +68,24 @@
typedef typename NodeVector::iterator NodeVectorIt;
protected:
-
+
/// \brief Data sturcture for path data.
- struct PathData {
+ struct PathData
+ {
bool found;
Length dist;
Edge pred;
- PathData(bool _found = false, Length _dist = 0) :
+ PathData(bool _found = false, Length _dist = 0) :
found(_found), dist(_dist), pred(INVALID) {}
- PathData(bool _found, Length _dist, Edge _pred) :
+ PathData(bool _found, Length _dist, Edge _pred) :
found(_found), dist(_dist), pred(_pred) {}
};
-
+
private:
-
- typedef typename Graph::template NodeMap > PathVectorNodeMap;
-
+
+ typedef typename Graph::template NodeMap >
+ PathDataNodeMap;
+
protected:
/// \brief Node map for storing path data.
@@ -92,7 +93,7 @@
/// Node map for storing path data of all nodes in the current
/// component. dmap[v][k] is the length of a shortest directed walk
/// to node v from the starting node containing exactly k edges.
- PathVectorNodeMap dmap;
+ PathDataNodeMap dmap;
/// \brief The directed graph the algorithm runs on.
const Graph& graph;
@@ -103,16 +104,20 @@
Length cycle_length;
/// \brief The number of edges in the found cycle.
int cycle_size;
+ /// \brief A node for obtaining a minimum mean cycle.
+ Node cycle_node;
+
/// \brief The found cycle.
Path *cycle_path;
- /// \brief The found cycle.
+ /// \brief The algorithm uses local \ref lemon::Path "Path"
+ /// structure to store the found cycle.
bool local_path;
/// \brief Node map for identifying strongly connected components.
IntNodeMap comp;
/// \brief The number of strongly connected components.
int comp_num;
- /// \brief %Counter for identifying the current component.
+ /// \brief Counter for identifying the current component.
int comp_cnt;
/// \brief Nodes of the current component.
NodeVector nodes;
@@ -129,8 +134,8 @@
/// \param _length The length (cost) of the edges.
MinMeanCycle( const Graph& _graph,
const LengthMap& _length ) :
- graph(_graph), length(_length), dmap(_graph),
- cycle_length(0), cycle_size(-1), comp(_graph),
+ graph(_graph), length(_length), dmap(_graph), comp(_graph),
+ cycle_length(0), cycle_size(-1), cycle_node(INVALID),
cycle_path(NULL), local_path(false)
{ }
@@ -140,15 +145,6 @@
}
protected:
-
- /// \brief Initializes the internal data structures.
- void init() {
- comp_num = stronglyConnectedComponents(graph, comp);
- if (!cycle_path) {
- local_path = true;
- cycle_path = new Path;
- }
- }
/// \brief Initializes the internal data structures for the current
/// component.
@@ -158,7 +154,6 @@
for (NodeIt v(graph); v != INVALID; ++v) {
if (comp[v] == comp_cnt) nodes.push_back(v);
}
-
// Creating vectors for all nodes
int n = nodes.size();
for (NodeVectorIt vi = nodes.begin(); vi != nodes.end(); ++vi) {
@@ -166,16 +161,19 @@
}
}
- /// \brief Processes all rounds of computing required path data.
+ /// \brief Processes all rounds of computing required path data for
+ /// the current component.
void processRounds() {
dmap[nodes[0]][0] = PathData(true, 0);
process.clear();
- for (OutEdgeIt oe(graph, nodes[0]); oe != INVALID; ++oe) {
- Node v = graph.target(oe);
+ // Processing the first round
+ for (OutEdgeIt e(graph, nodes[0]); e != INVALID; ++e) {
+ Node v = graph.target(e);
if (comp[v] != comp_cnt || v == nodes[0]) continue;
- dmap[v][1] = PathData(true, length[oe], oe);
+ dmap[v][1] = PathData(true, length[e], e);
process.push_back(v);
}
+ // Processing other rounds
int n = nodes.size(), k;
for (k = 2; k <= n && process.size() < n; ++k) {
processNextBuildRound(k);
@@ -190,12 +188,15 @@
void processNextBuildRound(int k) {
NodeVector next;
for (NodeVectorIt ui = process.begin(); ui != process.end(); ++ui) {
- for (OutEdgeIt oe(graph, *ui); oe != INVALID; ++oe) {
- Node v = graph.target(oe);
+ for (OutEdgeIt e(graph, *ui); e != INVALID; ++e) {
+ Node v = graph.target(e);
if (comp[v] != comp_cnt) continue;
- if ( !dmap[v][k].found || (dmap[v][k].dist > dmap[*ui][k-1].dist + length[oe]) ) {
- if (!dmap[v][k].found) next.push_back(v);
- dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[oe], oe);
+ if (!dmap[v][k].found) {
+ next.push_back(v);
+ dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[e], e);
+ }
+ else if (dmap[*ui][k-1].dist + length[e] < dmap[v][k].dist) {
+ dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[e], e);
}
}
}
@@ -206,44 +207,39 @@
/// using \ref nodes vector instead of \ref process vector.
void processNextFullRound(int k) {
for (NodeVectorIt ui = nodes.begin(); ui != nodes.end(); ++ui) {
- for (OutEdgeIt oe(graph, *ui); oe != INVALID; ++oe) {
- Node v = graph.target(oe);
+ for (OutEdgeIt e(graph, *ui); e != INVALID; ++e) {
+ Node v = graph.target(e);
if (comp[v] != comp_cnt) continue;
- if ( !dmap[v][k].found || (dmap[v][k].dist > dmap[*ui][k-1].dist + length[oe]) ) {
- dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[oe], oe);
+ if ( !dmap[v][k].found ||
+ dmap[*ui][k-1].dist + length[e] < dmap[v][k].dist ) {
+ dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[e], e);
}
}
}
}
- /// \brief Finds the minimum cycle mean value according to the path
- /// data stored in \ref dmap.
- ///
- /// Finds the minimum cycle mean value according to the path data
- /// stored in \ref dmap.
- ///
- /// \retval min_length The total length of the found cycle.
- /// \retval min_size The number of edges in the found cycle.
- /// \retval min_node A node for obtaining a critical cycle.
- ///
- /// \return \c true if a cycle exists in the graph.
- bool findMinCycleMean(Length &min_length, int &min_size, Node &min_node) {
+ /// \brief Finds the minimum cycle mean value in the current
+ /// component.
+ bool findCurrentMin(Length &min_length, int &min_size, Node &min_node) {
bool found_min = false;
for (NodeVectorIt vi = nodes.begin(); vi != nodes.end(); ++vi) {
+ int n = nodes.size();
+ if (!dmap[*vi][n].found) continue;
Length len;
int size;
bool found_one = false;
- int n = nodes.size();
for (int k = 0; k < n; ++k) {
+ if (!dmap[*vi][k].found) continue;
Length _len = dmap[*vi][n].dist - dmap[*vi][k].dist;
int _size = n - k;
- if ( dmap[*vi][n].found && dmap[*vi][k].found && (!found_one || len * _size < _len * size) ) {
+ if (!found_one || len * _size < _len * size) {
found_one = true;
len = _len;
size = _size;
}
}
- if (found_one && (!found_min || len * min_size < min_length * size)) {
+ if ( found_one &&
+ (!found_min || len * min_size < min_length * size) ) {
found_min = true;
min_length = len;
min_size = size;
@@ -253,94 +249,152 @@
return found_min;
}
- /// \brief Finds a critical (minimum mean) cycle according to the
- /// path data stored in \ref dmap.
- void findCycle(const Node &min_n) {
- IntNodeMap reached(graph, -1);
- int r = reached[min_n] = dmap[min_n].size() - 1;
- Node u = graph.source(dmap[min_n][r].pred);
- while (reached[u] < 0) {
- reached[u] = --r;
- u = graph.source(dmap[u][r].pred);
- }
- r = reached[u];
- Edge ce = dmap[u][r].pred;
- cycle_path->addFront(ce);
- Node v;
- while ((v = graph.source(ce)) != u) {
- ce = dmap[v][--r].pred;
- cycle_path->addFront(ce);
- }
- }
+ public:
- public:
-
/// \brief Runs the algorithm.
///
/// Runs the algorithm.
///
/// \return \c true if a cycle exists in the graph.
+ ///
+ /// \note Apart from the return value, m.run() is just a shortcut
+ /// of the following code.
+ /// \code
+ /// m.init();
+ /// m.findMinMean();
+ /// m.findCycle();
+ /// \endcode
bool run() {
init();
- // Searching for the minimum mean cycle in all components
- bool found_cycle = false;
- Node cycle_node;
+ findMinMean();
+ return findCycle();
+ }
+
+ /// \brief Initializes the internal data structures.
+ void init() {
+ comp_num = stronglyConnectedComponents(graph, comp);
+ if (!cycle_path) {
+ local_path = true;
+ cycle_path = new Path;
+ }
+ }
+
+ /// \brief Finds the minimum cycle mean value in the graph.
+ ///
+ /// Computes all the required path data and finds the minimum cycle
+ /// mean value in the graph.
+ ///
+ /// \return \c true if a cycle exists in the graph.
+ ///
+ /// \pre \ref init() must be called before using this function.
+ bool findMinMean() {
+ cycle_node = INVALID;
for (comp_cnt = 0; comp_cnt < comp_num; ++comp_cnt) {
-
initCurrent();
processRounds();
Length min_length;
int min_size;
Node min_node;
- bool found_min = findMinCycleMean(min_length, min_size, min_node);
+ bool found_min = findCurrentMin(min_length, min_size, min_node);
- if ( found_min && (!found_cycle || min_length * cycle_size < cycle_length * min_size) ) {
- found_cycle = true;
+ if ( found_min && (cycle_node == INVALID ||
+ min_length * cycle_size < cycle_length * min_size) ) {
cycle_length = min_length;
cycle_size = min_size;
cycle_node = min_node;
}
}
- if (found_cycle) findCycle(cycle_node);
- return found_cycle;
+ return (cycle_node != INVALID);
}
- /// \brief Returns the total length of the found critical cycle.
+ /// \brief Finds a critical (minimum mean) cycle.
///
- /// Returns the total length of the found critical cycle.
+ /// Finds a critical (minimum mean) cycle using the path data
+ /// stored in \ref dmap.
+ ///
+ /// \return \c true if a cycle exists in the graph.
+ ///
+ /// \pre \ref init() and \ref findMinMean() must be called before
+ /// using this function.
+ bool findCycle() {
+ if (cycle_node == INVALID) return false;
+ cycle_length = 0;
+ cycle_size = 0;
+ IntNodeMap reached(graph, -1);
+ int r = reached[cycle_node] = dmap[cycle_node].size() - 1;
+ Node u = graph.source(dmap[cycle_node][r].pred);
+ while (reached[u] < 0) {
+ reached[u] = --r;
+ u = graph.source(dmap[u][r].pred);
+ }
+ r = reached[u];
+ Edge e = dmap[u][r].pred;
+ cycle_path->addFront(e);
+ cycle_length = cycle_length + length[e];
+ ++cycle_size;
+ Node v;
+ while ((v = graph.source(e)) != u) {
+ e = dmap[v][--r].pred;
+ cycle_path->addFront(e);
+ cycle_length = cycle_length + length[e];
+ ++cycle_size;
+ }
+ return true;
+ }
+
+ /// \brief Resets the internal data structures.
+ ///
+ /// Resets the internal data structures so that \ref findMinMean()
+ /// and \ref findCycle() can be called again (e.g. when the
+ /// underlaying graph has been modified).
+ void reset() {
+ for (NodeIt u(graph); u != INVALID; ++u)
+ dmap[u].clear();
+ cycle_node = INVALID;
+ if (cycle_path) cycle_path->clear();
+ comp_num = stronglyConnectedComponents(graph, comp);
+ }
+
+ /// \brief Returns the total length of the found cycle.
+ ///
+ /// Returns the total length of the found cycle.
///
/// \pre \ref run() must be called before using this function.
Length cycleLength() const {
return cycle_length;
}
- /// \brief Returns the number of edges in the found critical
- /// cycle.
+ /// \brief Returns the number of edges in the found cycle.
///
- /// Returns the number of edges in the found critical cycle.
+ /// Returns the number of edges in the found cycle.
///
/// \pre \ref run() must be called before using this function.
int cycleEdgeNum() const {
return cycle_size;
}
- /// \brief Returns the mean length of the found critical cycle.
+ /// \brief Returns the mean length of the found cycle.
///
- /// Returns the mean length of the found critical cycle.
+ /// Returns the mean length of the found cycle.
///
/// \pre \ref run() must be called before using this function.
///
/// \warning LengthMap::Value must be convertible to double.
+ ///
+ /// \note m.minMean() is just a shortcut of the following code.
+ /// \code
+ /// return m.cycleEdgeNum() / double(m.cycleLength());
+ /// \endcode
double minMean() const {
- return (double)cycle_length / (double)cycle_size;
+ return cycle_length / (double)cycle_size;
}
/// \brief Returns a const reference to the \ref lemon::Path "Path"
- /// structure of the found flow.
+ /// structure of the found cycle.
///
/// Returns a const reference to the \ref lemon::Path "Path"
- /// structure of the found flow.
+ /// structure of the found cycle.
///
/// \pre \ref run() must be called before using this function.
///
diff -r 086fc76d591d -r 21eb3ccdc3df lemon/tolerance.h
--- a/lemon/tolerance.h Thu Mar 22 06:36:50 2007 +0000
+++ b/lemon/tolerance.h Thu Mar 22 15:40:50 2007 +0000
@@ -305,6 +305,73 @@
///Returns zero
static Value zero() {return 0;}
};
+
+
+ ///Long integer specialization of \ref Tolerance.
+
+ ///Long integer specialization of \ref Tolerance.
+ ///\sa Tolerance
+ template<>
+ class Tolerance
+ {
+ public:
+ ///\e
+ typedef long int Value;
+
+ ///\name Comparisons
+ ///See \ref Tolerance for more details.
+
+ ///@{
+
+ ///Returns \c true if \c a is \e surely strictly less than \c b
+ static bool less(Value a,Value b) { return aa; }
+ ///Returns \c true if \c a is \e surely non-zero
+ static bool nonZero(Value a) { return a!=0;};
+
+ ///@}
+
+ ///Returns zero
+ static Value zero() {return 0;}
+ };
+
+ ///Unsigned long integer specialization of \ref Tolerance.
+
+ ///Unsigned long integer specialization of \ref Tolerance.
+ ///\sa Tolerance
+ template<>
+ class Tolerance
+ {
+ public:
+ ///\e
+ typedef unsigned long int Value;
+
+ ///\name Comparisons
+ ///See \ref Tolerance for more details.
+
+ ///@{
+
+ ///Returns \c true if \c a is \e surely strictly less than \c b
+ static bool less(Value a,Value b) { return a DoubleMap;
+ typedef Graph::EdgeMap DoubleEdgeMap;
+ typedef Graph::NodeMap DoubleNodeMap;
std::string inputName;
std::string outputName;
@@ -115,19 +116,19 @@
if (mincostflow) {
Graph graph;
- Node s, t;
- DoubleMap cost(graph), capacity(graph);
- readDimacs(is, graph, capacity, s, t, cost);
+ DoubleNodeMap supply(graph);
+ DoubleEdgeMap lower(graph), capacity(graph), cost(graph);
+ readDimacs(is, graph, supply, lower, capacity, cost);
GraphWriter(os, graph).
+ writeNodeMap("supply", supply).
+ writeEdgeMap("lower", lower).
writeEdgeMap("capacity", capacity).
- writeNode("source", s).
- writeNode("target", t).
writeEdgeMap("cost", cost).
run();
} else if (maxflow) {
Graph graph;
Node s, t;
- DoubleMap capacity(graph);
+ DoubleEdgeMap capacity(graph);
readDimacs(is, graph, capacity, s, t);
GraphWriter(os, graph).
writeEdgeMap("capacity", capacity).
@@ -137,7 +138,7 @@
} else if (shortestpath) {
Graph graph;
Node s;
- DoubleMap capacity(graph);
+ DoubleEdgeMap capacity(graph);
readDimacs(is, graph, capacity, s);
GraphWriter(os, graph).
writeEdgeMap("capacity", capacity).
@@ -145,7 +146,7 @@
run();
} else if (capacitated) {
Graph graph;
- DoubleMap capacity(graph);
+ DoubleEdgeMap capacity(graph);
readDimacs(is, graph, capacity);
GraphWriter(os, graph).
writeEdgeMap("capacity", capacity).