0
2
0
| ... | ... |
@@ -33,16 +33,16 @@ |
| 33 | 33 |
namespace lemon {
|
| 34 | 34 |
|
| 35 | 35 |
/// \ingroup min_cut |
| 36 | 36 |
/// |
| 37 | 37 |
/// \brief Gomory-Hu cut tree algorithm |
| 38 | 38 |
/// |
| 39 |
/// The Gomory-Hu tree is a tree on the node set of the graph, but it |
|
| 40 |
/// may contain edges which are not in the original digraph. It has the |
|
| 39 |
/// The Gomory-Hu tree is a tree on the node set of a given graph, but it |
|
| 40 |
/// may contain edges which are not in the original graph. It has the |
|
| 41 | 41 |
/// property that the minimum capacity edge of the path between two nodes |
| 42 |
/// in this tree has the same weight as the minimum cut in the |
|
| 42 |
/// in this tree has the same weight as the minimum cut in the graph |
|
| 43 | 43 |
/// between these nodes. Moreover the components obtained by removing |
| 44 | 44 |
/// this edge from the tree determine the corresponding minimum cut. |
| 45 | 45 |
/// |
| 46 | 46 |
/// Therefore once this tree is computed, the minimum cut between any pair |
| 47 | 47 |
/// of nodes can easily be obtained. |
| 48 | 48 |
/// |
| ... | ... |
@@ -50,28 +50,32 @@ |
| 50 | 50 |
/// the \ref Preflow algorithm), therefore the algorithm has |
| 51 | 51 |
/// \f$(O(n^3\sqrt{e})\f$ overall time complexity. It calculates a
|
| 52 | 52 |
/// rooted Gomory-Hu tree, its structure and the weights can be obtained |
| 53 | 53 |
/// by \c predNode(), \c predValue() and \c rootDist(). |
| 54 | 54 |
/// |
| 55 | 55 |
/// The members \c minCutMap() and \c minCutValue() calculate |
| 56 |
/// the minimum cut and the minimum cut value between any two node |
|
| 57 |
/// in the digraph. You can also list (iterate on) the nodes and the |
|
| 58 |
/// |
|
| 56 |
/// the minimum cut and the minimum cut value between any two nodes |
|
| 57 |
/// in the graph. You can also list (iterate on) the nodes and the |
|
| 58 |
/// edges of the cuts using \c MinCutNodeIt and \c MinCutEdgeIt. |
|
| 59 | 59 |
/// |
| 60 |
/// \tparam GR The undirected graph data structure the algorithm will run on |
|
| 61 |
/// \tparam CAP type of the EdgeMap describing the Edge capacities. |
|
| 62 |
/// |
|
| 60 |
/// \tparam GR The type of the undirected graph the algorithm runs on. |
|
| 61 |
/// \tparam CAP The type of the edge map describing the edge capacities. |
|
| 62 |
/// It is \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>" by default. |
|
| 63 |
#ifdef DOXYGEN |
|
| 63 | 64 |
template <typename GR, |
| 64 |
typename CAP = typename GR::template EdgeMap<int> |
|
| 65 |
> |
|
| 65 |
typename CAP> |
|
| 66 |
#else |
|
| 67 |
template <typename GR, |
|
| 68 |
typename CAP = typename GR::template EdgeMap<int> > |
|
| 69 |
#endif |
|
| 66 | 70 |
class GomoryHu {
|
| 67 | 71 |
public: |
| 68 | 72 |
|
| 69 | 73 |
/// The graph type |
| 70 | 74 |
typedef GR Graph; |
| 71 |
/// The type |
|
| 75 |
/// The type of the edge capacity map |
|
| 72 | 76 |
typedef CAP Capacity; |
| 73 | 77 |
/// The value type of capacities |
| 74 | 78 |
typedef typename Capacity::Value Value; |
| 75 | 79 |
|
| 76 | 80 |
private: |
| 77 | 81 |
|
| ... | ... |
@@ -111,14 +115,14 @@ |
| 111 | 115 |
|
| 112 | 116 |
public: |
| 113 | 117 |
|
| 114 | 118 |
/// \brief Constructor |
| 115 | 119 |
/// |
| 116 | 120 |
/// Constructor |
| 117 |
/// \param graph The graph the algorithm will run on. |
|
| 118 |
/// \param capacity The capacity map. |
|
| 121 |
/// \param graph The undirected graph the algorithm runs on. |
|
| 122 |
/// \param capacity The edge capacity map. |
|
| 119 | 123 |
GomoryHu(const Graph& graph, const Capacity& capacity) |
| 120 | 124 |
: _graph(graph), _capacity(capacity), |
| 121 | 125 |
_pred(0), _weight(0), _order(0) |
| 122 | 126 |
{
|
| 123 | 127 |
checkConcept<concepts::ReadMap<Edge, Value>, Capacity>(); |
| 124 | 128 |
} |
| ... | ... |
@@ -128,16 +132,15 @@ |
| 128 | 132 |
/// |
| 129 | 133 |
/// Destructor |
| 130 | 134 |
~GomoryHu() {
|
| 131 | 135 |
destroyStructures(); |
| 132 | 136 |
} |
| 133 | 137 |
|
| 134 |
// \brief Initialize the internal data structures. |
|
| 135 |
// |
|
| 136 |
// This function initializes the internal data structures. |
|
| 137 |
// |
|
| 138 |
private: |
|
| 139 |
|
|
| 140 |
// Initialize the internal data structures |
|
| 138 | 141 |
void init() {
|
| 139 | 142 |
createStructures(); |
| 140 | 143 |
|
| 141 | 144 |
_root = NodeIt(_graph); |
| 142 | 145 |
for (NodeIt n(_graph); n != INVALID; ++n) {
|
| 143 | 146 |
_pred->set(n, _root); |
| ... | ... |
@@ -145,18 +148,13 @@ |
| 145 | 148 |
} |
| 146 | 149 |
_pred->set(_root, INVALID); |
| 147 | 150 |
_weight->set(_root, std::numeric_limits<Value>::max()); |
| 148 | 151 |
} |
| 149 | 152 |
|
| 150 | 153 |
|
| 151 |
// \brief Start the algorithm |
|
| 152 |
// |
|
| 153 |
// This function starts the algorithm. |
|
| 154 |
// |
|
| 155 |
// \pre \ref init() must be called before using this function. |
|
| 156 |
// |
|
| 154 |
// Start the algorithm |
|
| 157 | 155 |
void start() {
|
| 158 | 156 |
Preflow<Graph, Capacity> fa(_graph, _capacity, _root, INVALID); |
| 159 | 157 |
|
| 160 | 158 |
for (NodeIt n(_graph); n != INVALID; ++n) {
|
| 161 | 159 |
if (n == _root) continue; |
| 162 | 160 |
|
| ... | ... |
@@ -195,12 +193,14 @@ |
| 195 | 193 |
_order->set(st.back(), index++); |
| 196 | 194 |
st.pop_back(); |
| 197 | 195 |
} |
| 198 | 196 |
} |
| 199 | 197 |
} |
| 200 | 198 |
|
| 199 |
public: |
|
| 200 |
|
|
| 201 | 201 |
///\name Execution Control |
| 202 | 202 |
|
| 203 | 203 |
///@{
|
| 204 | 204 |
|
| 205 | 205 |
/// \brief Run the Gomory-Hu algorithm. |
| 206 | 206 |
/// |
| ... | ... |
@@ -212,14 +212,14 @@ |
| 212 | 212 |
|
| 213 | 213 |
/// @} |
| 214 | 214 |
|
| 215 | 215 |
///\name Query Functions |
| 216 | 216 |
///The results of the algorithm can be obtained using these |
| 217 | 217 |
///functions.\n |
| 218 |
///The \ref run() "run()" should be called before using them.\n |
|
| 219 |
///See also MinCutNodeIt and MinCutEdgeIt |
|
| 218 |
///\ref run() "run()" should be called before using them.\n |
|
| 219 |
///See also \ref MinCutNodeIt and \ref MinCutEdgeIt. |
|
| 220 | 220 |
|
| 221 | 221 |
///@{
|
| 222 | 222 |
|
| 223 | 223 |
/// \brief Return the predecessor node in the Gomory-Hu tree. |
| 224 | 224 |
/// |
| 225 | 225 |
/// This function returns the predecessor node in the Gomory-Hu tree. |
| ... | ... |
@@ -247,13 +247,13 @@ |
| 247 | 247 |
} |
| 248 | 248 |
|
| 249 | 249 |
/// \brief Return the minimum cut value between two nodes |
| 250 | 250 |
/// |
| 251 | 251 |
/// This function returns the minimum cut value between two nodes. The |
| 252 | 252 |
/// algorithm finds the nearest common ancestor in the Gomory-Hu |
| 253 |
/// tree and calculates the minimum weight |
|
| 253 |
/// tree and calculates the minimum weight edge on the paths to |
|
| 254 | 254 |
/// the ancestor. |
| 255 | 255 |
Value minCutValue(const Node& s, const Node& t) const {
|
| 256 | 256 |
Node sn = s, tn = t; |
| 257 | 257 |
Value value = std::numeric_limits<Value>::max(); |
| 258 | 258 |
|
| 259 | 259 |
while (sn != tn) {
|
| ... | ... |
@@ -268,27 +268,25 @@ |
| 268 | 268 |
return value; |
| 269 | 269 |
} |
| 270 | 270 |
|
| 271 | 271 |
/// \brief Return the minimum cut between two nodes |
| 272 | 272 |
/// |
| 273 | 273 |
/// This function returns the minimum cut between the nodes \c s and \c t |
| 274 |
/// the \r cutMap parameter by setting the nodes in the component of |
|
| 275 |
/// \c \s to true and the other nodes to false. |
|
| 274 |
/// in the \c cutMap parameter by setting the nodes in the component of |
|
| 275 |
/// \c s to \c true and the other nodes to \c false. |
|
| 276 | 276 |
/// |
| 277 |
/// The \c cutMap should be \ref concepts::ReadWriteMap |
|
| 278 |
/// "ReadWriteMap". |
|
| 279 |
/// |
|
| 280 |
/// For higher level interfaces, see MinCutNodeIt and MinCutEdgeIt |
|
| 277 |
/// For higher level interfaces, see MinCutNodeIt and MinCutEdgeIt. |
|
| 281 | 278 |
template <typename CutMap> |
| 282 |
Value minCutMap(const Node& s, ///< |
|
| 279 |
Value minCutMap(const Node& s, ///< The base node. |
|
| 283 | 280 |
const Node& t, |
| 284 |
///< The node you want to separate from |
|
| 281 |
///< The node you want to separate from node \c s. |
|
| 285 | 282 |
CutMap& cutMap |
| 286 |
///< The cut will be return in this map. |
|
| 287 |
/// It must be a \c bool \ref concepts::ReadWriteMap |
|
| 288 |
/// |
|
| 283 |
///< The cut will be returned in this map. |
|
| 284 |
/// It must be a \c bool (or convertible) |
|
| 285 |
/// \ref concepts::ReadWriteMap "ReadWriteMap" |
|
| 286 |
/// on the graph nodes. |
|
| 289 | 287 |
) const {
|
| 290 | 288 |
Node sn = s, tn = t; |
| 291 | 289 |
bool s_root=false; |
| 292 | 290 |
Node rn = INVALID; |
| 293 | 291 |
Value value = std::numeric_limits<Value>::max(); |
| 294 | 292 |
|
| ... | ... |
@@ -345,32 +343,32 @@ |
| 345 | 343 |
/// |
| 346 | 344 |
/// This example counts the nodes in the minimum cut separating \c s from |
| 347 | 345 |
/// \c t. |
| 348 | 346 |
/// \code |
| 349 | 347 |
/// GomoruHu<Graph> gom(g, capacities); |
| 350 | 348 |
/// gom.run(); |
| 351 |
/// int sum=0; |
|
| 352 |
/// for(GomoruHu<Graph>::MinCutNodeIt n(gom,s,t);n!=INVALID;++n) ++sum; |
|
| 349 |
/// int cnt=0; |
|
| 350 |
/// for(GomoruHu<Graph>::MinCutNodeIt n(gom,s,t); n!=INVALID; ++n) ++cnt; |
|
| 353 | 351 |
/// \endcode |
| 354 | 352 |
class MinCutNodeIt |
| 355 | 353 |
{
|
| 356 | 354 |
bool _side; |
| 357 | 355 |
typename Graph::NodeIt _node_it; |
| 358 | 356 |
typename Graph::template NodeMap<bool> _cut; |
| 359 | 357 |
public: |
| 360 | 358 |
/// Constructor |
| 361 | 359 |
|
| 362 |
/// Constructor |
|
| 360 |
/// Constructor. |
|
| 363 | 361 |
/// |
| 364 | 362 |
MinCutNodeIt(GomoryHu const &gomory, |
| 365 | 363 |
///< The GomoryHu class. You must call its |
| 366 | 364 |
/// run() method |
| 367 |
/// before initializing this iterator |
|
| 368 |
const Node& s, ///< Base node |
|
| 365 |
/// before initializing this iterator. |
|
| 366 |
const Node& s, ///< The base node. |
|
| 369 | 367 |
const Node& t, |
| 370 |
///< The node you want to separate from |
|
| 368 |
///< The node you want to separate from node \c s. |
|
| 371 | 369 |
bool side=true |
| 372 | 370 |
///< If it is \c true (default) then the iterator lists |
| 373 | 371 |
/// the nodes of the component containing \c s, |
| 374 | 372 |
/// otherwise it lists the other component. |
| 375 | 373 |
/// \note As the minimum cut is not always unique, |
| 376 | 374 |
/// \code |
| ... | ... |
@@ -395,37 +393,37 @@ |
| 395 | 393 |
{
|
| 396 | 394 |
gomory.minCutMap(s,t,_cut); |
| 397 | 395 |
for(_node_it=typename Graph::NodeIt(gomory._graph); |
| 398 | 396 |
_node_it!=INVALID && _cut[_node_it]!=_side; |
| 399 | 397 |
++_node_it) {}
|
| 400 | 398 |
} |
| 401 |
/// Conversion to Node |
|
| 399 |
/// Conversion to \c Node |
|
| 402 | 400 |
|
| 403 |
/// Conversion to Node |
|
| 401 |
/// Conversion to \c Node. |
|
| 404 | 402 |
/// |
| 405 | 403 |
operator typename Graph::Node() const |
| 406 | 404 |
{
|
| 407 | 405 |
return _node_it; |
| 408 | 406 |
} |
| 409 | 407 |
bool operator==(Invalid) { return _node_it==INVALID; }
|
| 410 | 408 |
bool operator!=(Invalid) { return _node_it!=INVALID; }
|
| 411 | 409 |
/// Next node |
| 412 | 410 |
|
| 413 |
/// Next node |
|
| 411 |
/// Next node. |
|
| 414 | 412 |
/// |
| 415 | 413 |
MinCutNodeIt &operator++() |
| 416 | 414 |
{
|
| 417 | 415 |
for(++_node_it;_node_it!=INVALID&&_cut[_node_it]!=_side;++_node_it) {}
|
| 418 | 416 |
return *this; |
| 419 | 417 |
} |
| 420 | 418 |
/// Postfix incrementation |
| 421 | 419 |
|
| 422 |
/// Postfix incrementation |
|
| 420 |
/// Postfix incrementation. |
|
| 423 | 421 |
/// |
| 424 | 422 |
/// \warning This incrementation |
| 425 |
/// returns a \c Node, not a \ |
|
| 423 |
/// returns a \c Node, not a \c MinCutNodeIt, as one may |
|
| 426 | 424 |
/// expect. |
| 427 | 425 |
typename Graph::Node operator++(int) |
| 428 | 426 |
{
|
| 429 | 427 |
typename Graph::Node n=*this; |
| 430 | 428 |
++(*this); |
| 431 | 429 |
return n; |
| ... | ... |
@@ -443,17 +441,17 @@ |
| 443 | 441 |
/// This example computes the value of the minimum cut separating \c s from |
| 444 | 442 |
/// \c t. |
| 445 | 443 |
/// \code |
| 446 | 444 |
/// GomoruHu<Graph> gom(g, capacities); |
| 447 | 445 |
/// gom.run(); |
| 448 | 446 |
/// int value=0; |
| 449 |
/// for(GomoruHu<Graph>::MinCutEdgeIt e(gom,s,t);e!=INVALID;++e) |
|
| 447 |
/// for(GomoruHu<Graph>::MinCutEdgeIt e(gom,s,t); e!=INVALID; ++e) |
|
| 450 | 448 |
/// value+=capacities[e]; |
| 451 | 449 |
/// \endcode |
| 452 | 450 |
/// the result will be the same as it is returned by |
| 453 |
/// \ref GomoryHu:: |
|
| 451 |
/// \ref GomoryHu::minCutValue() "gom.minCutValue(s,t)" |
|
| 454 | 452 |
class MinCutEdgeIt |
| 455 | 453 |
{
|
| 456 | 454 |
bool _side; |
| 457 | 455 |
const Graph &_graph; |
| 458 | 456 |
typename Graph::NodeIt _node_it; |
| 459 | 457 |
typename Graph::OutArcIt _arc_it; |
| ... | ... |
@@ -470,16 +468,16 @@ |
| 470 | 468 |
} |
| 471 | 469 |
|
| 472 | 470 |
public: |
| 473 | 471 |
MinCutEdgeIt(GomoryHu const &gomory, |
| 474 | 472 |
///< The GomoryHu class. You must call its |
| 475 | 473 |
/// run() method |
| 476 |
/// before initializing this iterator |
|
| 477 |
const Node& s, ///< Base node |
|
| 474 |
/// before initializing this iterator. |
|
| 475 |
const Node& s, ///< The base node. |
|
| 478 | 476 |
const Node& t, |
| 479 |
///< The node you want to separate from |
|
| 477 |
///< The node you want to separate from node \c s. |
|
| 480 | 478 |
bool side=true |
| 481 | 479 |
///< If it is \c true (default) then the listed arcs |
| 482 | 480 |
/// will be oriented from the |
| 483 | 481 |
/// the nodes of the component containing \c s, |
| 484 | 482 |
/// otherwise they will be oriented in the opposite |
| 485 | 483 |
/// direction. |
| ... | ... |
@@ -501,47 +499,46 @@ |
| 501 | 499 |
for(++_node_it; _node_it!=INVALID&&!_cut[_node_it]; ++_node_it) {}
|
| 502 | 500 |
if(_node_it!=INVALID) |
| 503 | 501 |
_arc_it= typename Graph::OutArcIt(_graph,_node_it); |
| 504 | 502 |
} |
| 505 | 503 |
while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step(); |
| 506 | 504 |
} |
| 507 |
/// Conversion to Arc |
|
| 505 |
/// Conversion to \c Arc |
|
| 508 | 506 |
|
| 509 |
/// Conversion to Arc |
|
| 507 |
/// Conversion to \c Arc. |
|
| 510 | 508 |
/// |
| 511 | 509 |
operator typename Graph::Arc() const |
| 512 | 510 |
{
|
| 513 | 511 |
return _arc_it; |
| 514 | 512 |
} |
| 515 |
/// Conversion to Edge |
|
| 513 |
/// Conversion to \c Edge |
|
| 516 | 514 |
|
| 517 |
/// Conversion to Edge |
|
| 515 |
/// Conversion to \c Edge. |
|
| 518 | 516 |
/// |
| 519 | 517 |
operator typename Graph::Edge() const |
| 520 | 518 |
{
|
| 521 | 519 |
return _arc_it; |
| 522 | 520 |
} |
| 523 | 521 |
bool operator==(Invalid) { return _node_it==INVALID; }
|
| 524 | 522 |
bool operator!=(Invalid) { return _node_it!=INVALID; }
|
| 525 | 523 |
/// Next edge |
| 526 | 524 |
|
| 527 |
/// Next edge |
|
| 525 |
/// Next edge. |
|
| 528 | 526 |
/// |
| 529 | 527 |
MinCutEdgeIt &operator++() |
| 530 | 528 |
{
|
| 531 | 529 |
step(); |
| 532 | 530 |
while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step(); |
| 533 | 531 |
return *this; |
| 534 | 532 |
} |
| 535 | 533 |
/// Postfix incrementation |
| 536 | 534 |
|
| 537 |
/// Postfix incrementation |
|
| 535 |
/// Postfix incrementation. |
|
| 538 | 536 |
/// |
| 539 | 537 |
/// \warning This incrementation |
| 540 |
/// returns a \c Arc, not a \ref MinCutEdgeIt, as one may |
|
| 541 |
/// expect. |
|
| 538 |
/// returns an \c Arc, not a \c MinCutEdgeIt, as one may expect. |
|
| 542 | 539 |
typename Graph::Arc operator++(int) |
| 543 | 540 |
{
|
| 544 | 541 |
typename Graph::Arc e=*this; |
| 545 | 542 |
++(*this); |
| 546 | 543 |
return e; |
| 547 | 544 |
} |
| ... | ... |
@@ -58,13 +58,12 @@ |
| 58 | 58 |
|
| 59 | 59 |
std::istringstream input(test_lgf); |
| 60 | 60 |
GraphReader<Graph>(graph, input). |
| 61 | 61 |
edgeMap("capacity", capacity).run();
|
| 62 | 62 |
|
| 63 | 63 |
GomoryHu<Graph> ght(graph, capacity); |
| 64 |
ght.init(); |
|
| 65 | 64 |
ght.run(); |
| 66 | 65 |
|
| 67 | 66 |
for (NodeIt u(graph); u != INVALID; ++u) {
|
| 68 | 67 |
for (NodeIt v(graph); v != u; ++v) {
|
| 69 | 68 |
Preflow<Graph, IntEdgeMap> pf(graph, capacity, u, v); |
| 70 | 69 |
pf.runMinCut(); |
0 comments (0 inline)