Advertisement
Guest User

Untitled

a guest
Oct 17th, 2019
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.02 KB | None | 0 0
  1. #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
  2. #include <CGAL/Delaunay_triangulation_2.h>
  3. #include <CGAL/Triangulation_vertex_base_with_info_2.h>
  4. #include <CGAL/Point_set_2.h>
  5.  
  6. #include <vector>
  7. #include <iostream>
  8. #include <algorithm>
  9. #include <iterator>
  10. #include <unordered_set>
  11. #include <queue>
  12. #include <list>
  13. using namespace std;
  14.  
  15. #define PRINT2D(vecvec) for(int i = 0; i < vecvec.size(); i++){cout<<i<<" neighbourhood: "; for(auto x : vecvec[i]){cout<<x<<" ";} cout<<endl;}
  16. #define PRINT1D(vec) for(int x : vec){cout<<x<<" ";} cout<<endl;
  17.  
  18. typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
  19. typedef CGAL::Triangulation_vertex_base_with_info_2<int, K> Vb;
  20. typedef CGAL::Triangulation_data_structure_2<Vb> Tds;  
  21. typedef CGAL::Delaunay_triangulation_2<K, Tds> Delaunay0;
  22. typedef CGAL::Point_set_2<K, Tds> Delaunay;  
  23.  
  24. typedef Delaunay::Point Point;      
  25. typedef Delaunay::Edge_iterator Edge_iterator;
  26. typedef Delaunay::Vertex_handle Vertex_handle;
  27.  
  28. typedef vector<pair<double, double> > Points_list;
  29. typedef vector<vector<int> > Neighbour_list;
  30. typedef pair<int, int> Edge;
  31.  
  32. const int K_NEAREST = 10;
  33.  
  34. Neighbour_list build_Delaunay_graph(Delaunay& T, int points_amount) {
  35.    Neighbour_list neighbour_list(points_amount);
  36.    vector<unordered_set<int> > unique_edges(points_amount);
  37.    Delaunay::Finite_vertices_iterator vit;
  38.  
  39.    // Triangulation edges
  40.    Delaunay::Vertex_circulator vc, done;
  41.    for (vit = T.finite_vertices_begin(); vit != T.finite_vertices_end(); ++vit)
  42.    {
  43.       int act_point = vit->info();
  44.       vc = vit->incident_vertices();
  45.       done = vc;
  46.       if (vc != 0)
  47.       {
  48.          do {
  49.             if (T.is_infinite(vc)) continue;
  50.             unique_edges[act_point].insert(vc->info());
  51.             unique_edges[vc->info()].insert(act_point);
  52.          } while(++vc != done);
  53.      }
  54.    }
  55.  
  56.    // 10 nearest Edges
  57.    for (vit = T.finite_vertices_begin(); vit != T.finite_vertices_end(); ++vit)
  58.    {
  59.       vector <Vertex_handle> L;    
  60.       int act_point = vit->info();
  61.       T.nearest_neighbors( vit, K_NEAREST+1, back_inserter(L) );
  62.       for (int i=0; i< L.size(); i++)
  63.       {
  64.          if(L[i]->info() != act_point){
  65.             unique_edges[act_point].insert(L[i]->info());
  66.             unique_edges[L[i]->info()].insert(act_point);
  67.          }
  68.       }
  69.          
  70.    }
  71.  
  72.    for(int i = 0; i < points_amount; i++) {
  73.       for(const int &el : unique_edges[i]) {
  74.          neighbour_list[i].push_back(el);
  75.       }
  76.    }
  77.  
  78.    return neighbour_list;
  79. }
  80.  
  81. inline double euclid_sq_distance(int v, int w, Points_list& points) {
  82.    double x = points[v].first - points[w].first;
  83.    double y = points[v].second - points[w].second;
  84.    return x*x+y*y;
  85. }
  86.  
  87. class Prim {
  88.    Neighbour_list neighbour_list;
  89.    int vertex_amount;
  90.    vector<bool> used;
  91.    priority_queue<pair<double, Edge> > tree_dist;
  92.    Points_list points_list;
  93.  
  94.    public:
  95.    Prim(Neighbour_list neighbour_list, Points_list points_list, int vertex_amount) {
  96.       this->neighbour_list = neighbour_list;
  97.       this->vertex_amount = vertex_amount;
  98.       this->points_list = points_list;
  99.       vector<bool> t(vertex_amount);
  100.       for(int i = 0; i < vertex_amount; i++) {
  101.          t[i] = false;
  102.       }
  103.       this->used = t;
  104.    }
  105.    
  106.    vector<Edge> spanning_tree() {
  107.       used[0] = true;
  108.       relax(0);
  109.       vector<Edge> tree;
  110.  
  111.       while (tree.size() != vertex_amount-1){
  112.          Edge closest = get_closest_edge();
  113.          tree.push_back(closest);
  114.          relax(closest.second);
  115.          used[closest.second] = true;
  116.       }
  117.       return tree;
  118.    }
  119.  
  120.    private:
  121.    Edge get_closest_edge() {
  122.       int res = -1;
  123.       while(tree_dist.size()){
  124.          Edge top = tree_dist.top().second;
  125.          tree_dist.pop();
  126.          if(!used[top.second]) {
  127.             return top;
  128.          }
  129.       }
  130.       return make_pair(0, 0);
  131.    }
  132.  
  133.    void relax(int vertex) {
  134.       for(int neigh : neighbour_list[vertex]) {
  135.          if(!used[neigh]){
  136.             tree_dist.push(make_pair(-euclid_sq_distance(vertex, neigh, points_list), make_pair(vertex, neigh)));
  137.          }
  138.       }
  139.    }
  140. };
  141.  
  142. Neighbour_list build_doubled_leafs_tree(vector<Edge>& tree, int vertex_amount) {
  143.    Neighbour_list neighbour_list(vertex_amount);
  144.    for(auto edge : tree) {
  145.       neighbour_list[edge.first].push_back(edge.second);
  146.       neighbour_list[edge.second].push_back(edge.first);
  147.    }
  148.    for(int i = 0; i < vertex_amount; i++){
  149.       if(neighbour_list[i].size() == 1){
  150.          neighbour_list[i].push_back(neighbour_list[i][0]);
  151.          neighbour_list[neighbour_list[i][0]].push_back(i);
  152.       }
  153.    }
  154.    return neighbour_list;
  155. }
  156.  
  157. vector<int> convex_hull_to_tsp(vector<int>& odd, Points_list& points_list, vector<int>& convex_hull){
  158.    priority_queue<pair<double, int> > q;
  159.    unordered_set<int> not_on_hull;
  160.    for(int i = 0; i < odd.size(); i++){
  161.       bool on_hull = false;
  162.       for(int j = 0; j < convex_hull.size(); j++){
  163.          if(odd[i] == convex_hull[j]){
  164.             on_hull = true;
  165.             break;
  166.          }
  167.       }
  168.       if(!on_hull){
  169.          not_on_hull.insert(odd[i]);
  170.       }
  171.    }
  172.    list<int> tsp;
  173.    for(int x : convex_hull){
  174.       tsp.push_back(x);
  175.    }
  176.  
  177.    // initialize queue
  178.    for(int vert : not_on_hull){
  179.       double min_dist = 0;
  180.       for(int j = 0; j < convex_hull.size(); j++){
  181.          min_dist = min(min_dist, euclid_sq_distance(vert, convex_hull[j], points_list));
  182.       }
  183.       q.push(make_pair(min_dist, vert));
  184.    }
  185.  
  186.    while(not_on_hull.size() != 0){
  187.       auto top = q.top();
  188.       q.pop();
  189.       if(not_on_hull.find(top.second) == not_on_hull.end()){
  190.          continue;
  191.       }
  192.       not_on_hull.erase(top.second);
  193.       auto minimizing_vert = tsp.begin();
  194.       auto it = tsp.begin();
  195.       while(next(it) != tsp.end()){
  196.          auto prev = it;
  197.          it++;
  198.          double long dist = sqrt(euclid_sq_distance(*it, top.second, points_list)) + sqrt(euclid_sq_distance(*prev, top.second, points_list));
  199.          if(dist < sqrt(euclid_sq_distance(*minimizing_vert, top.second, points_list)) + sqrt(euclid_sq_distance(*(next(minimizing_vert)), top.second, points_list))){
  200.             minimizing_vert = prev;
  201.          }
  202.       }
  203.       auto prev = it;
  204.       it = tsp.begin();
  205.       double long dist = sqrt(euclid_sq_distance(*it, top.second, points_list)) + sqrt(euclid_sq_distance(*prev, top.second, points_list));
  206.       if(dist < sqrt(euclid_sq_distance(*minimizing_vert, top.second, points_list)) + sqrt(euclid_sq_distance(*(next(minimizing_vert)), top.second, points_list))){
  207.          minimizing_vert = prev;
  208.       }
  209.       tsp.insert(minimizing_vert, top.second);
  210.    }
  211.  
  212.    vector<int> result;
  213.    for(int x : tsp){
  214.       result.push_back(x);
  215.    }
  216.    return result;
  217. }
  218.  
  219. vector<int> get_odd_vertices(Neighbour_list& neighbour_list, int vertex_amount){
  220.    vector<int> result;
  221.    for(int i = 0; i < vertex_amount; i++){
  222.       if(neighbour_list[i].size() % 2){
  223.          result.push_back(i);
  224.       }
  225.    }
  226.    return result;
  227. }
  228.  
  229. vector<Edge> matching_from_tsp(vector<int> tsp, Points_list& points_list){
  230.    if(tsp.size() == 2){
  231.       return {make_pair(tsp[0], tsp[1])};
  232.    }
  233.    vector<Edge> odd;
  234.    vector<Edge> even;
  235.    for(int i = 0; i < tsp.size() - 3; i += 2){
  236.       odd.push_back(make_pair(tsp[i], tsp[i+1]));
  237.       even.push_back(make_pair(tsp[i+1], tsp[i+2]));
  238.    }
  239.    odd.push_back(make_pair(tsp[tsp.size()-2], tsp[tsp.size()-1]));
  240.    even.push_back(make_pair(tsp[tsp.size()-1], tsp[0]));
  241.    double odd_cost, even_cost;
  242.    odd_cost = even_cost = 0;
  243.  
  244.    for(Edge e : odd){
  245.       odd_cost += sqrt(euclid_sq_distance(e.first, e.second, points_list));
  246.    }
  247.    for(Edge e : even){
  248.       even_cost += sqrt(euclid_sq_distance(e.first, e.second, points_list));
  249.    }
  250.    if(odd_cost < even_cost){
  251.       return odd;
  252.    } else {
  253.       return even;
  254.    }
  255. }
  256.  
  257. Edge ord_edge(int x, int y){return make_pair(min(x, y), max(x, y));}
  258.  
  259. void find_euler_cycle(map<Edge, int>& edges_cnt, Neighbour_list& neighbour_list, vector<int>& result, int vert){
  260.    for(int i = neighbour_list[vert].size() - 1; i >= 0; i--){
  261.       int next = neighbour_list[vert][i];
  262.       if(edges_cnt[ord_edge(vert, neighbour_list[vert][i])] != 0){
  263.          edges_cnt[ord_edge(vert, next)]--;
  264.          neighbour_list[vert].pop_back();
  265.          find_euler_cycle(edges_cnt, neighbour_list, result, next);
  266.       } else {
  267.          neighbour_list[vert].pop_back();
  268.       }
  269.    }
  270.    result.push_back(vert);
  271. }
  272.  
  273. vector<int> euler_cycle(Neighbour_list neighbour_list, int vertex_amount){
  274.    map<Edge, int> edges_cnt;
  275.    for(int i = 0; i < vertex_amount; i++){
  276.       for(int j = 0; j < neighbour_list[i].size(); j++){
  277.          if(edges_cnt.find(ord_edge(i, neighbour_list[i][j])) != edges_cnt.end()){
  278.             edges_cnt[ord_edge(i, neighbour_list[i][j])]++;
  279.          } else {
  280.             edges_cnt[ord_edge(i, neighbour_list[i][j])] = 1;
  281.          }
  282.       }
  283.    }
  284.    for(auto entry : edges_cnt){edges_cnt[entry.first] = entry.second /= 2;}
  285.    vector<int> result;
  286.    find_euler_cycle(edges_cnt, neighbour_list, result, 0);
  287.    cout<<"przed return"<<endl;
  288.    return result;
  289. }
  290.  
  291. vector<int> euler_cycle_to_tsp(vector<int> euler_cycle, int vertex_amount){
  292.    vector<int> result;
  293.    vector<bool> used(vertex_amount);
  294.    for(int x : euler_cycle){
  295.       if(!used[x]){
  296.          used[x] = true;
  297.          result.push_back(x);
  298.       }
  299.    }
  300.    return result;
  301. }
  302.  
  303. vector<int> get_aprox_tsp(Points_list& points_list, vector<pair<Point, int> >& points, int vertex_amount){
  304.    Delaunay T;
  305.    T.insert(points.begin(), points.end());
  306.    Neighbour_list neighbour_list = build_Delaunay_graph(T, vertex_amount);
  307.    Prim prim = Prim(neighbour_list, points_list, vertex_amount);
  308.    vector<Edge> tree = prim.spanning_tree();
  309.    neighbour_list = build_doubled_leafs_tree(tree, vertex_amount);
  310.    
  311.    Delaunay K;
  312.    points.clear();
  313.    vector<int> odd = get_odd_vertices(neighbour_list, vertex_amount);
  314.    for (int i=0; i<odd.size(); i++)
  315.    {  
  316.       points.push_back( make_pair(Point(points_list[odd[i]].first,points_list[odd[i]].second), odd[i]) );
  317.    }
  318.    K.insert(points.begin(), points.end());
  319.  
  320.    vector<int> convex_hull;
  321.    Delaunay::Vertex_circulator vc, done;
  322.    vc = K.incident_vertices(K.infinite_vertex()),
  323.    done = vc;
  324.    if (vc != 0)
  325.    {
  326.      do { convex_hull.push_back(vc->info());
  327.         } while(++vc != done);
  328.    }
  329.  
  330.    vector<int> partial_tsp = convex_hull_to_tsp(odd, points_list, convex_hull);
  331.    vector<Edge> matching = matching_from_tsp(partial_tsp, points_list);
  332.    for(Edge e : matching){
  333.       neighbour_list[e.first].push_back(e.second);
  334.       neighbour_list[e.second].push_back(e.first);
  335.    }
  336.  
  337.    PRINT2D(neighbour_list);
  338.  
  339.    vector<int> euler = euler_cycle(neighbour_list, vertex_amount);
  340.    cout<<"po return"<<endl;
  341.    vector<int> res = euler_cycle_to_tsp(euler, vertex_amount);
  342.    return res;
  343. }
  344.  
  345. double tsp_cost(vector<int> tsp_cycle, Points_list& points_list, int vertex_amount){
  346.    double result = 0;
  347.    for(int i = 0; i < vertex_amount - 1; i++){
  348.       result += sqrt(euclid_sq_distance(tsp_cycle[i], tsp_cycle[i+1], points_list));
  349.    }
  350.    result += sqrt(euclid_sq_distance(tsp_cycle[vertex_amount - 1], tsp_cycle[0], points_list));
  351.    return result;
  352. }
  353.  
  354. void read_input(vector<pair<Point, int> >& points, Points_list& points_list, int& n) {
  355.    double x,y;
  356.    cin >> n;
  357.    for (int i=0; i<n; i++)
  358.    {
  359.       cin >> x >> y;      
  360.       points.push_back( make_pair(Point(x,y), i) );
  361.       points_list.push_back( make_pair(x, y) );
  362.    }
  363. }
  364.  
  365. int main( )
  366. {
  367.    int zes;
  368.    cin>>zes;
  369.    while(zes--){
  370.       vector<pair<Point, int> > points;
  371.       Points_list points_list;
  372.       int vertex_amount;
  373.      
  374.       read_input(points, points_list, vertex_amount);
  375.      
  376.       vector<int> tsp_cycle = get_aprox_tsp(points_list, points, vertex_amount);
  377.       cout<<tsp_cycle.size()<<endl;
  378.       PRINT1D(tsp_cycle);
  379.       for(int x : tsp_cycle){
  380.          cout<<x<<" ";
  381.       }
  382.       cout<<endl<<tsp_cost(tsp_cycle, points_list, vertex_amount)<<endl;
  383.  
  384.       return 0;
  385.    }
  386. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement