#include "testlib.h" #include #include #include using namespace std; using ll = unsigned long long; using pll = pair; const double eps = 1e-3; void generate_edges(int thread_id, unsigned int seed, ll n, double pm, ll start_node, ll end_node, vector> &output) { random_t thread_rnd; thread_rnd.setSeed(seed); for (ll s = start_node; s <= end_node; ++s) { for (ll e = 1; e <= n; ++e) { if (s == e) continue; if (thread_rnd.next(1.0) < pm) { double len = thread_rnd.next(eps, 1.0 / eps); output.push_back({{s, e}, len}); } } } } int main(int argc, char *argv[]) { registerGen(argc, argv, 1); ll n = opt("N"); double pm = opt("pm"); ensuref(0 <= pm && pm <= 1, "pm must be in [0, 1]: %lf", pm); // ll m_approx = n * (n - 1) * pm; unsigned int n_threads = thread::hardware_concurrency(); if (n_threads == 0) n_threads = 2; vector seeds(n_threads); for (unsigned int i = 0; i < n_threads; ++i) { seeds[i] = rnd.next(numeric_limits::min(), numeric_limits::max()); } vector threads; vector>> thread_outputs(n_threads); ll nodes_per_thread = (n + n_threads - 1) / n_threads; for (unsigned int i = 0; i < n_threads; ++i) { ll start_node = i * nodes_per_thread + 1; ll end_node = min((i + 1) * nodes_per_thread, n); if (start_node > end_node) continue; threads.emplace_back(generate_edges, i, seeds[i], n, pm, start_node, end_node, ref(thread_outputs[i])); } vector> E; for (unsigned int i = 0; i < threads.size(); ++i) { threads[i].join(); E.insert(E.end(), thread_outputs[i].begin(), thread_outputs[i].end()); } shuffle(E.begin(), E.end()); println(n, E.size()); for (auto [p, l] : E) println(p.first, p.second, l); }