#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