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