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