【模板】随机数据生成器
最近打了一次 Codeforces ,发现有很多小 bug 其实可以用随机数据 + assert 就能找出来的。而且也能验证一些猜想或者打表。每次都写这个东西太耗时间了。现在临时写一个后面慢慢完善。
namespace RandomGenerator {
const int MAXN = 500;
const int MAXM = 200000;
const int MAXAI = 100;
const int rnd_seed = chrono::system_clock::now().time_since_epoch().count();
//const int rnd_seed = 19937;
mt19937_64 rnd (rnd_seed); // 调用rnd()生成uint_64_t类型
ll randInt (ll x) {
// [1, x]
return rnd() % x + 1;
}
ll randInt (ll l, ll r) {
// [l, r],可以有负数
return rnd() % (r - l + 1) + l;
}
void genArray (int &n, int *a) {
n = randInt (MAXN);
for (int i = 1; i <= n; ++i) {
a[i] = randInt (MAXAI);
}
}
void genTree (int &n, int *p) {
// 生成一棵树,p[i]表示i节点的父亲是谁,且p[i]<i
// 根一定是1
n = randInt (MAXN);
p[1] = 0;
for (int i = 2; i <= n; ++i) {
p[i] = randInt (1, i - 1);
}
}
void genTree (int &n, int *x, int *y) {
n = randInt (MAXN);
pii g[MAXN];
g[1] = {0, 0};
for (int i = 2; i <= n; ++i) {
g[i] = {i, randInt (1, i - 1) };
}
random_shuffle (g + 1 + 1, g + 1 + n);
for (int i = 1; i <= n - 1; ++i) {
if (rnd() % 2 == 1) {
swap (g[i + 1].first, g[i + 1].second);
}
x[i] = g[i + 1].first;
y[i] = g[i + 1].second;
}
// WTN (x, n - 1);
// WTN (y, n - 1);
}
void genGraph (int &n, int &m, int *x, int *y) {
genTree (n, x, y);
m = randInt (n - 1, min (1LL * MAXM, 1LL * n * (n - 1) / 2));
set<pii> S;
for (int i = 1; i <= n - 1; ++i) {
pii pi = {x[i], y[i]};
if (pi.first > pi.second) {
swap (pi.first, pi.second);
}
S.insert (pi);
}
for (int i = n; i <= m; ++i) {
x[i] = randInt (n);
y[i] = randInt (n);
if (x[i] == y[i]) {
--i;
continue;
}
if (x[i] > y[i]) {
swap (x[i], y[i]);
}
if (S.count ({x[i], y[i]})) {
--i;
continue;
}
S.insert ({x[i], y[i]});
}
assert (S.size() == m);
vector<pii> V (S.begin(), S.end());
random_shuffle (V.begin(), V.end());
for (int i = 1; i <= m; ++i) {
x[i] = V[i - 1].first;
y[i] = V[i - 1].second;
if (rnd() % 2 == 1) {
swap (x[i], y[i]);
}
}
}
};
using namespace RandomGenerator;
int n;
int x[200005];
int y[200005];
vector<int> G[200005];
bool vis[200005];
int cnt = 0;
void dfs (int u) {
++cnt;
vis[u] = 1;
// printf ("u=%d\n", u);
for (int v : G[u]) {
if (vis[v] == 1) {
// printf (" v=%d u=%d\n", v, u);
continue;
};
// printf (" v=%d u=%d\n", v, u);
dfs (v);
}
}
void solve() {
int m;
genTree (n, x, y);
WT (n);
// WTN (x, m);
// WTN (y, m);
for (int i = 1; i <= n; ++i) {
G[i].clear();
vis[i] = 0;
}
for (int i = 1; i <= n - 1; ++i) {
G[x[i]].push_back (y[i]);
G[y[i]].push_back (x[i]);
}
cnt = 0;
dfs (1);
assert (cnt == n);
puts ("?");
}
目前好像只能生成随机的联通图,且(无重边无自环),通过正确限制m的上限才能跑出结果。可能后面可以生成一些不平衡的树或者不平衡的图(菊花图)看一下复杂度。