Files
BMSSP/generator/gen4.cpp
2025-10-30 20:30:31 +09:00

98 lines
2.4 KiB
C++

#include "testlib.h"
#include <iomanip>
#include <thread>
#include <tuple>
#include <unordered_map>
#include <vector>
using namespace std;
using ll = unsigned long long;
using pll = pair<ll, ll>;
const double eps = 1e-3;
void generate_edges_parallel(ll s_start, ll s_end, ll n, const vector<ll> &cnt,
unsigned int thread_seed,
vector<tuple<ll, ll, double>> &buffer) {
random_t thread_rnd;
thread_rnd.setSeed(thread_seed);
unordered_map<ll, ll> selected;
for (ll s = s_start; s < s_end; ++s) {
ll k = cnt[s];
if (k == 0) continue;
selected.clear();
for (ll i = 0; i < k; ++i) {
ll range_size = (n - 1) - i;
ll j = thread_rnd.next(1uLL, range_size);
ll val_j = selected.count(j) ? selected[j] : j;
ll val_last =
selected.count(range_size) ? selected[range_size] : range_size;
ll e = (val_j < s) ? val_j : val_j + 1;
double len = thread_rnd.next(eps, 1.0 / eps);
buffer.emplace_back(s, e, len);
selected[j] = val_last;
}
}
}
int main(int argc, char *argv[]) {
// 메인 RNG 초기화
registerGen(argc, argv, 1);
ll n = opt<ll>("N");
ll m = opt<ll>("M");
println(n, m);
vector<ll> cnt(n + 1, 0);
for (ll i = 0; i < m; ++i) {
ll s = rnd.next(1uLL, n);
cnt[s]++;
}
const int num_threads = thread::hardware_concurrency();
vector<thread> threads;
vector<unsigned int> thread_seeds;
vector<vector<tuple<ll, ll, double>>> thread_buffers(num_threads);
for (int i = 0; i < num_threads; ++i) {
thread_seeds.push_back(rnd.next(1u, 1000000u));
}
ll s_batch_size = (n + num_threads) / num_threads;
ll s_current = 1;
for (int i = 0; i < num_threads; ++i) {
ll s_start = s_current;
ll s_end = min(s_start + s_batch_size, n + 1);
if (s_start >= s_end) break;
threads.emplace_back(generate_edges_parallel, s_start, s_end, n,
ref(cnt), thread_seeds[i], ref(thread_buffers[i]));
s_current = s_end;
}
for (auto &t : threads) {
t.join();
}
cout << fixed << setprecision(15);
for (int i = 0; i < num_threads; ++i) {
for (const auto &edge : thread_buffers[i]) {
println(get<0>(edge), get<1>(edge), get<2>(edge));
}
}
}