diff -r 4980b05606bd -r ae0b056593a7 lemon/christofides_tsp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/christofides_tsp.h Sat Jan 08 21:59:56 2011 +0100 @@ -0,0 +1,129 @@ +#ifndef LEMON_CHRISTOFIDES_TSP_H +#define LEMON_CHRISTOFIDES_TSP_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace lemon { + + namespace christofides_helper { + template + L vectorConvert(const std::vector &_path) { + return L(_path.begin(), _path.end()); + } + + template <> + std::vector vectorConvert(const std::vector &_path) { + return _path; + } + } + + template + class ChristofidesTsp { + private: + GRAPH_TYPEDEFS(SmartGraph); + + public: + typedef typename CM::Value Cost; + typedef SmartGraph::EdgeMap CostMap; + + ChristofidesTsp(const FullGraph &gr, const CM &cost) : _cost(_gr), fullg(gr), fullcost(cost), nr(_gr) { + graphCopy(gr, _gr).nodeCrossRef(nr).edgeMap(cost, _cost).run(); + } + + Cost run() { + _path.clear(); + + SmartGraph::EdgeMap tree(_gr); + kruskal(_gr, _cost, tree); + + FilterEdges treefiltered(_gr, tree); + InDegMap > deg(treefiltered); + + SmartGraph::NodeMap oddfilter(_gr, false); + FilterNodes oddNodes(_gr, oddfilter); + + for (NodeIt n(_gr); n!=INVALID; ++n) { + if (deg[n]%2 == 1) { + oddNodes.enable(n); + } + } + + NegMap negmap(_cost); + MaxWeightedPerfectMatching, + NegMap > perfmatch(oddNodes, negmap); + perfmatch.run(); + + for (FilterNodes::EdgeIt e(oddNodes); e!=INVALID; ++e) { + if (perfmatch.matching(e)) { + treefiltered.enable(_gr.addEdge(_gr.u(e), _gr.v(e))); + } + } + + FilterEdges::NodeMap seen(treefiltered, false); + for (EulerIt > e(treefiltered); e!=INVALID; ++e) { + if (seen[treefiltered.target(e)]==false) { + _path.push_back(nr[treefiltered.target(e)]); + seen[treefiltered.target(e)] = true; + } + } + + _sum = fullcost[ fullg.edge(_path.back(), _path.front()) ]; + for (unsigned int i=0; i<_path.size()-1; ++i) + _sum += fullcost[ fullg.edge(_path[i], _path[i+1]) ]; + + return _sum; + } + + template + void tourNodes(L &container) { + container(christofides_helper::vectorConvert(_path)); + } + + template