Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <cmath>
- #include <map>
- #include <set>
- double dist(std::pair<int, int> x, std::pair<int, int> y) {
- return std::pow(std::pow(x.first - y.first, 2) + std::pow(x.second - y.second, 2), 0.5);
- }
- int DSU_get(int node, std::vector<int>& trees) {
- return (node == trees[node]) ? node : (trees[node] = DSU_get(trees[node], trees));
- }
- void DSU_unite(int node1, int node2, std::vector<int>& trees) {
- node1 = DSU_get(node1, trees);
- node2 = DSU_get(node2, trees);
- if (rand() & 1) {
- std::swap(node1, node2);
- }
- if (node1 != node2) {
- trees[node1] = node2;
- }
- }
- std::pair<int, int> step(int x_min, int x_max, int y_min, int y_max) {
- int step_x = 0, step_y = 0;
- if (x_max - x_min <= 50) {
- step_x = 1;
- } else if (x_max - x_min <= 100) {
- step_x = 2;
- } else if (x_max - x_min <= 300) {
- step_x = 5;
- } else if (x_max - x_min <= 500) {
- step_x = 10;
- } else if (x_max - x_min <= 1000) {
- step_x = 20;
- } else if (x_max - x_min <= 2000) {
- step_x = 40;
- } else if (x_max - x_min <= 5000) {
- step_x = 80;
- } else {
- step_x = 150;
- }
- if (y_max - y_min <= 50) {
- step_y = 1;
- } else if (y_max - y_min <= 100) {
- step_y = 2;
- } else if (y_max - y_min <= 300) {
- step_y = 5;
- } else if (y_max - y_min <= 500) {
- step_y = 10;
- } else if (y_max - y_min <= 1000) {
- step_y = 20;
- } else if (y_max - y_min <= 2000) {
- step_y = 40;
- } else if (y_max - y_min <= 5000) {
- step_y = 80;
- } else {
- step_y = 150;
- }
- return (std::make_pair(step_x, step_y));
- }
- double Cruscal(int count_node, std::vector<std::pair<double, std::pair<int, int>>>& graph) {
- std::vector<int> trees(count_node);
- for (int i = 0; i != count_node; ++i) {
- trees[i] = i;
- }
- int node1, node2;
- double result_weight = 0.0, weight;
- std::sort(graph.begin(), graph.end());
- for (size_t i = 0; i != graph.size(); ++i) {
- node1 = graph[i].second.first;
- node2 = graph[i].second.second;
- weight = graph[i].first;
- if (DSU_get(node1, trees) != DSU_get(node2, trees)) {
- result_weight += weight;
- DSU_unite(node1, node2, trees);
- }
- }
- return result_weight;
- }
- int main() {
- int count_town, count_rout, x, y;
- std::cin >> count_town >> count_rout;
- std::map<std::pair<int ,int>, int> code;
- std::vector<std::pair<int, int>> nodes;
- std::set<std::pair<int ,int>> nodes_set;
- std::pair<int, int> par;
- int x_min = 100000, x_max = 0, y_min = 100000, y_max = 0;
- for (int i = 0; i != count_town; ++i) {
- std::cin >> x >> y;
- if (x > x_max) {
- x_max = x;
- }
- if (x < x_min) {
- x_min = x;
- }
- if (y > y_max) {
- y_max = y;
- }
- if (y < y_min) {
- y_min = y;
- }
- par = std::make_pair(x, y);
- nodes.push_back(par);
- nodes_set.insert(par);
- code[par] = i;
- }
- std::pair<int, int> steps = step(x_min, x_max, y_min, y_max);
- std::vector<std::pair<double, std::pair<int, int>>> graph, graph_cur;
- for (size_t i = 0; i != nodes.size(); ++i) {
- for (size_t j = i + 1; j != nodes.size(); ++j) {
- graph.push_back(std::make_pair(dist(nodes[i], nodes[j]),
- std::make_pair(code[nodes[i]], code[nodes[j]])));
- }
- }
- double cur_val = 0;
- std::pair<int ,int> best;
- std::set<std::pair<int, int>> solve;
- double min_weight = Cruscal(count_town, graph), min_weight_cur = min_weight;
- for (size_t z = 0; z != count_rout; ++z) {
- for (int i = x_min; i != x_max + 1; i += steps.first) {
- for (int j = y_min; j != y_max + 1; j += steps.second) {
- if (nodes_set.find(std::make_pair(i, j)) == nodes_set.end()) {
- graph_cur = graph;
- par = std::make_pair(i, j);
- for (size_t k = 0; k != count_town; ++k) {
- graph_cur.push_back(std::make_pair(dist(nodes[k], par),
- std::make_pair(code[nodes[k]], count_town)));
- }
- cur_val = Cruscal(count_town + 1, graph_cur);
- if (cur_val < min_weight_cur) {
- min_weight_cur = cur_val;
- best = par;
- }
- }
- }
- }
- if (min_weight != min_weight_cur) {
- min_weight = min_weight_cur;
- for (size_t k = 0; k != count_town; ++k) {
- graph.push_back(std::make_pair(dist(nodes[k], best),
- std::make_pair(code[nodes[k]], count_town)));
- }
- ++count_town;
- solve.insert(best);
- nodes.push_back(best);
- nodes_set.insert(best);
- } else {
- break;
- }
- }
- std::cout << solve.size() << std::endl;
- for (auto x : solve) {
- std::cout << x.first << " " << x.second << std::endl;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement