#include #include #include #include #include #include using namespace std; typedef set SI; typedef long long LL; const int MAXT = 50; const int MAXN = 100; const int MAXM = 200; const LL MAXC = 10000; struct bundle { SI b; LL c; }; typedef vector VB; int cases = MAXT; //either a and b are disjoint, or one is contained in the other (can be equal) bool ok(const SI& a, const SI& b) { if (a.size() > b.size()) return ok(b, a); auto ai = a.begin(), bi = b.begin(); int cnt = 0; while (ai != a.end() && bi != b.end()) { if (*ai < *bi) ++ai; else if (*ai > *bi) ++bi; else { ++cnt; ++ai; ++bi; } } return cnt == 0 || cnt == a.size(); } //the items are already numbered from 1 to n void dump(const VB& v, int n) { assert(cases > 0); assert(1 <= n && n <= MAXN); assert(1 <= v.size() && v.size() <= MAXM); vector f(n, false); cout << n << ' ' << v.size() << endl; for (int i = 0; i < v.size(); ++i) { assert(1 <= v[i].c && v[i].c <= MAXC); //can actually check for laminarity in linear time, //will do if we use larger data for (int j = 0; j < i; ++j) assert(ok(v[i].b, v[j].b)); cout << v[i].c << ' ' << v[i].b.size(); for (auto x : v[i].b) { cout << ' ' << x; f[x-1] = true; } cout << endl; } for (auto x : f) assert(x); --cases; } void jumble(VB& v, int n) { vector p(v.size()), nx(n); for (int i = 0; i < v.size(); ++i) p[i] = i; for (int i = 0; i < n; ++i) nx[i] = i+1; for (int i = v.size()-1; i > 0; --i) swap(p[i], p[rand()%(i+1)]); for (int i = n-1; i > 0; --i) swap(nx[i], nx[rand()%(i+1)]); VB tmp(v.size()); for (int i = 0; i < v.size(); ++i) { tmp[i].c = v[p[i]].c; for (auto x : v[p[i]].b) tmp[i].b.insert(nx[x-1]); } v = tmp; } void init_b(int n, bundle& b) { b.b.clear(); b.c = MAXC; for (int i = 1; i <= n; ++i) b.b.insert(i); } int clamp(LL c, LL l, LL h) { return max(l, min(c, h)); } void tweak(LL& c, int i) { c += rand()%(3*i+1) - 2*i; c = max(LL(1), min(c, MAXC)); } void split(const bundle& b, VB& v, bool keep, int m) { if (v.size() == m) return; //if (keep || rand()%8) v.push_back(b); v.push_back(b); if (rand()%b.b.size() == 0) return; bundle lb, rb; for (auto x : b.b) { if (rand()&1) lb.b.insert(x); else rb.b.insert(x); } lb.c = b.c*lb.b.size()/b.b.size(); rb.c = b.c - lb.c; tweak(lb.c, lb.b.size()); tweak(rb.c, rb.b.size()); if (lb.b.size()) split(lb, v, false, m); if (rb.b.size()) split(rb, v, false, m); } void gen_rand(int n, int m) { bundle b; init_b(n, b); VB v; split(b, v, true, m); assert(v[0].b.size() == n); jumble(v, n); dump(v, n); } int main() { cout << cases << endl; while (cases > 10) { int m = 50 + rand()%(MAXM-50+1); clamp(m, 50, MAXM); gen_rand(MAXN, m); } while (cases) gen_rand(MAXN, MAXM); assert(cases == 0); }