#ifndef LEMON_GREEDY_TSP_H #define LEMON_GREEDY_TSP_H #include #include #include #include namespace lemon { namespace greedy_tsp_helper { template class KeyComp { typedef typename CostMap::Key Key; const CostMap &cost; public: KeyComp(const CostMap &_cost) : cost(_cost) {} bool operator() (const Key &a, const Key &b) const { return cost[a] < cost[b]; } }; 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 GreedyTsp { private: GRAPH_TYPEDEFS(FullGraph); public: typedef CM CostMap; typedef typename CM::Value Cost; GreedyTsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost) {} Cost run() { typedef UnionFind > Union; _nodes.clear(); std::vector path; path.resize(_gr.nodeNum()*2, -1); std::vector sorted_edges; sorted_edges.reserve(_gr.edgeNum()); for (EdgeIt n(_gr); n != INVALID; ++n) sorted_edges.push_back(n); std::sort(sorted_edges.begin(), sorted_edges.end(), greedy_tsp_helper::KeyComp(_cost)); FullGraph::NodeMap nodemap(_gr); Union unionfind(nodemap); for (NodeIt n(_gr); n != INVALID; ++n) unionfind.insert(n); FullGraph::NodeMap degree(_gr, 0); int nodesNum = 0, i = 0; while ( nodesNum != _gr.nodeNum()-1 ) { const Edge &e = sorted_edges[i]; const Node u = _gr.u(e), v = _gr.v(e); if (degree[u]<=1 && degree[v]<=1) { if (unionfind.join(u, v)) { ++degree[u]; ++degree[v]; ++nodesNum; const int uid = _gr.id(u), vid = _gr.id(v); path[uid*2 + (path[uid*2]==-1 ? 0 : 1)] = vid; path[vid*2 + (path[vid*2]==-1 ? 0 : 1)] = uid; } } ++i; } for (int i=0, n=-1; i<_gr.nodeNum()*2; ++i) { if (path[i] == -1) { if (n==-1) { n = i; } else { path[n] = i/2; path[i] = n/2; break; } } } for (int i=0, j=0, last=-1; i!=_gr.nodeNum(); ++i) { _nodes.push_back(_gr.nodeFromId(j)); if (path[2*j] != last) { last = j; j = path[2*j]; } else { last = j; j = path[2*j+1]; } } _sum = _cost[_gr.edge(_nodes.back(), _nodes.front())]; for (unsigned int i=0; i<_nodes.size()-1; ++i) _sum += _cost[_gr.edge(_nodes[i], _nodes[i+1])]; return _sum; } template void tourNodes(L &container) { container(greedy_tsp_helper::vectorConvert(_nodes)); } template