In the city of M, N new microdistricts are being built, between which M main roads are planned. Each road has its own construction cost Pij. Last year, the municipality managed to build K of these M roads. Unfortunately, this year it was decided to reduce the financing of construction, and now from the planned but not built MK roads, it is necessary to leave such that at least one way exists from any neighborhood to any other, but the cost of their construction is minimal (guaranteed that such a set exists).
What is the minimum cost P of the completion of the road network construction under the new plan, and how many new roads on it are to be built?
#include <iostream> #include <vector> #include <algorithm> /* * */ template <class T> struct Triplet { T first; // , T second; // , T third; // }; /* * UnionFind */ template <class T> class UF_element { public: T parent; // T size; // UF_element() {} UF_element(T id) : size(1) , parent(id) { } }; template <class T> class UnionFind { private: std::vector<UF_element<T>> Elements; public: /* * , */ UnionFind(T n) : Elements(n + 1) { for (register T i = 1; i < n + 1; ++i) { Elements[i] = UF_element<T>(i); } } /* * . * (log n), * O(1) */ T find(T id){ UF_element<T>& current = Elements[id]; while (current.parent != Elements[current.parent].parent){ current.parent = Elements[current.parent].parent; } return current.parent; } void merge(T a, T b) { UF_element<T>& UF_elem_A = Elements[find(a)]; UF_element<T>& UF_elem_B = Elements[find(b)]; if(UF_elem_A.parent == UF_elem_B.parent) return; if(UF_elem_A.size < UF_elem_B.size) { UF_elem_A.parent = b; UF_elem_B.size += UF_elem_A.size; } else { UF_elem_B.parent = a; UF_elem_A.size += UF_elem_B.size; } } }; template <typename T> bool comp(const Triplet<T>& a, const Triplet<T>& b) { return (a.third < b.third); } template <typename T> void kruskal(std::vector<Triplet<T>>& data, size_t& cost, size_t& count, const size_t& n) { UnionFind<T> N(n); for (size_t i = 0; i < data.size(); ++i) { if (N.find(data[i].first) != N.find(data[i].second)) { if (data[i].third) { // 0 (. ) cost += data[i].third; // ++count; // , } N.merge(data[i].first, data[i].second); } } } /* * */ template <typename T> void read_unlocked(T &out) { T c = getchar_unlocked(); for (; '0' <= c && c <= '9' ; c = getchar_unlocked()) { if (c == ' ' || c == '\n') return; out = out * 10 + c - '0'; } } int main() { std::ios_base::sync_with_stdio(false); size_t count = 0, cost = 0; // . @ilammy unsigned int n = 0, m = 0; read_unlocked(n); read_unlocked(m); std::vector<Triplet<unsigned int>> input(m); for (size_t i = 0; i < m; ++i) { read_unlocked(input[i].first); read_unlocked(input[i].second); read_unlocked(input[i].third); } std::sort(input.begin(), input.end(), comp<unsigned int>); kruskal(input, cost, count, n); std::cout << cost << " " << count << '\n'; }
struct A { char a; long int b; int c; };
struct B { char a; int c; long int b; };
UF_element(T id) : size(1) , parent(id) { }
UF_element(T id) { size = 1; parent = id; }
register is an automatic memory class specifier. Applies to objects located in local memory by default. It is a “request” (optional for execution) to the compiler about placing the values ​​of objects declared with the register specifier in one of the available registers, and not in the local memory.
for (register T i = 1; i < n + 1; ++i) { idElements[i] = UF_element<T>(i); }
UnionFind(T n) : Elements(n + 1) // { for (register T i = 1; i < n + 1; ++i) { Elements[i] = UF_element<T>(i); // } }
/* * : * - , * - , */ template <typename T> void write_unlocked(T inp, char last=' ') { if (!inp) { putchar_unlocked('0'); putchar_unlocked(last); return; } T out = 0; unsigned char sz_inp = 0; // for (; inp; inp /= 10, ++sz_inp) { out = (out << 3) + (out << 1) + inp % 10; } // for (; out; out /= 10, --sz_inp) { putchar_unlocked(out % 10 + '0'); } // , for (;sz_inp; --sz_inp) { putchar_unlocked('0'); } putchar_unlocked(last); }
Source: https://habr.com/ru/post/256929/
All Articles