Start
This commit is contained in:
50
generator/gen1.cpp
Normal file
50
generator/gen1.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "testlib.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
using ll = unsigned long long;
|
||||
using pll = pair<ll, ll>;
|
||||
|
||||
const double eps = 1e-3;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
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]++;
|
||||
}
|
||||
|
||||
unordered_map<ll, ll> selected;
|
||||
|
||||
for (ll s = 1; s <= n; ++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 = 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 = rnd.next(eps, 1.0 / eps);
|
||||
|
||||
println(s, e, len);
|
||||
|
||||
selected[j] = val_last;
|
||||
}
|
||||
}
|
||||
}
|
||||
80
generator/gen2.cpp
Normal file
80
generator/gen2.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
|
||||
#include "testlib.h"
|
||||
|
||||
#include <map>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
using ll = unsigned long long;
|
||||
using pll = pair<ll, ll>;
|
||||
|
||||
const double eps = 1e-3;
|
||||
|
||||
struct EdgeData {
|
||||
ll s, e;
|
||||
double len;
|
||||
};
|
||||
|
||||
void generate_edges(int thread_id, unsigned int seed, ll n, ll count,
|
||||
vector<EdgeData> &output) {
|
||||
random_t thread_rnd;
|
||||
thread_rnd.setSeed(seed);
|
||||
|
||||
output.reserve(count);
|
||||
|
||||
for (ll i = 0; i < count; ++i) {
|
||||
ll s = thread_rnd.next(1uLL, n);
|
||||
ll e = thread_rnd.next(1uLL, n);
|
||||
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<ll>("N");
|
||||
double pm = opt<double>("pm");
|
||||
|
||||
ensuref(0 <= pm && pm <= 1, "pm must be in [0, 1]: %lf", pm);
|
||||
ll m = n * (n - 1) * pm;
|
||||
|
||||
unsigned int n_threads = thread::hardware_concurrency();
|
||||
if (n_threads == 0) n_threads = 2;
|
||||
|
||||
vector<unsigned int> seeds(n_threads);
|
||||
for (unsigned int i = 0; i < n_threads; ++i) {
|
||||
seeds[i] = rnd.next();
|
||||
}
|
||||
|
||||
vector<thread> threads;
|
||||
vector<vector<EdgeData>> thread_outputs(n_threads);
|
||||
ll edges_per_thread = (m + n_threads - 1) / n_threads;
|
||||
|
||||
for (unsigned int i = 0; i < n_threads; ++i) {
|
||||
threads.emplace_back(generate_edges, i, seeds[i], n, edges_per_thread,
|
||||
ref(thread_outputs[i]));
|
||||
}
|
||||
|
||||
map<pll, double> edges;
|
||||
for (unsigned int i = 0; i < n_threads; ++i) {
|
||||
threads[i].join();
|
||||
|
||||
for (const auto &data : thread_outputs[i]) {
|
||||
if (edges.size() >= m) break;
|
||||
if (data.s == data.e) continue;
|
||||
if (edges.count({data.s, data.e})) continue;
|
||||
edges[{data.s, data.e}] = data.len;
|
||||
}
|
||||
}
|
||||
|
||||
vector<pair<pll, double>> E;
|
||||
for (auto [p, l] : edges) E.push_back({p, l});
|
||||
shuffle(E.begin(), E.end());
|
||||
|
||||
println(n, m);
|
||||
for (auto [p, l] : E) println(p.first, p.second, l);
|
||||
}
|
||||
75
generator/gen3.cpp
Normal file
75
generator/gen3.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "testlib.h"
|
||||
|
||||
#include <limits>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
using ll = unsigned long long;
|
||||
using pll = pair<ll, ll>;
|
||||
|
||||
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<pair<pll, double>> &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<ll>("N");
|
||||
double pm = opt<double>("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<unsigned int> seeds(n_threads);
|
||||
for (unsigned int i = 0; i < n_threads; ++i) {
|
||||
seeds[i] = rnd.next(numeric_limits<unsigned int>::min(),
|
||||
numeric_limits<unsigned int>::max());
|
||||
}
|
||||
|
||||
vector<thread> threads;
|
||||
vector<vector<pair<pll, double>>> 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<pair<pll, double>> 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);
|
||||
}
|
||||
97
generator/gen4.cpp
Normal file
97
generator/gen4.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user