結果
問題 |
No.2987 Colorful University of Tree
|
ユーザー |
|
提出日時 | 2025-05-25 01:17:23 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,081 ms / 5,000 ms |
コード長 | 5,829 bytes |
コンパイル時間 | 3,035 ms |
コンパイル使用メモリ | 231,196 KB |
実行使用メモリ | 98,900 KB |
最終ジャッジ日時 | 2025-05-25 01:17:52 |
合計ジャッジ時間 | 27,012 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 42 |
ソースコード
#include <bits/stdc++.h> using namespace std; // #define LOCK_GETCHAR // #define USE_INT_128 // #undef DEBUG #ifdef DEBUG #include <moeebius/debug.hpp> #else #define debug(...) (void(0)) #define Debug(...) (void(0)) #endif #define ENABLE_IF_INT , enable_if_t<_is_integer<T>, int> = 0 template <class T> constexpr bool _is_integer = numeric_limits<T>::is_integer; template <> constexpr bool _is_integer<bool> = false; template <> constexpr bool _is_integer<char> = false; #ifdef USE_INT_128 template <> constexpr bool _is_integer<__int128> = true; template <> constexpr bool _is_integer<__uint128_t> = true; #endif #if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(LOCK_GETCHAR) #define getchar getchar_unlocked #endif #define il inline #define mkp make_pair #define fi first #define se second #define ssz(x) (signed((x).size())) #define beg2ed(x) (x).begin(), (x).end() #define _loop_i_t(j, k) make_signed_t<decltype((j) - (k))> #define For(i, j, k) for (_loop_i_t(j, k) i = (j); i <= (k); ++i) #define ForDown(i, j, k) for (_loop_i_t(j, k) i = (j); i >= decltype(i)(k); --i) #define eb emplace_back #ifndef ONLINE_JUDGE #define FileIO(filename) \ freopen(filename ".in", "r", stdin); \ freopen(filename ".out", "w", stdout) #else #define FileIO(filename) void(0) #endif using ll = long long; using uint = unsigned int; using ull = unsigned long long; using db = double; using ldb = long double; using pii = pair<int, int>; using pll = pair<ll, ll>; #ifdef USE_INT_128 using lll = __int128_t; using ulll = __uint128_t; #endif // clang-format off constexpr il ll qpow(ll x, ull y, ll mod){ ll ans = 1; x %= mod; while (y) { if (y & 1) (ans *= x) %= mod; (x *= x) %= mod; y >>= 1; } return ans; } template<typename T> constexpr il void cmin(T & x, const T &y){ x = min(x, y); } template<typename T> constexpr il void cmax(T & x, const T &y){ x = max(x, y); } template<typename T ENABLE_IF_INT> il void read(T &x){ x = 0; int f = 1; int c = getchar(); while (!isdigit(c)) { if (c == '-') f = -1; c = getchar(); } while (isdigit(c)) { x = x * 10 + (c - '0'); c = getchar(); } x *= f; } template<typename T, typename ... Args> il void read(T &x, Args &... y){ read(x), read(y...); } // clang-format on // File head end namespace { constexpr ll MAXN = 2e5 + 5; int Tc, n, val[MAXN], id[MAXN], sum[MAXN]; pii E[MAXN]; vector<int> T[MAXN]; vector<pii> G[MAXN], G2[MAXN]; mt19937 rnd(12345); map<pii, int> col; map<int, pii> mp[MAXN]; bool is_todo[MAXN]; void solve() { read(n); col.clear(); For(i, 0, n) mp[i].clear(), is_todo[i] = 0, G[i].clear(), G2[i].clear(), T[i].clear(), val[i] = id[i] = sum[i] = 0, E[i] = {}; int cnt = 0, ans = 0; For(i, 1, n) { int len; read(len), T[i].resize(len), cnt += (len & 1); cmax(ans, len); for (int &e : T[i]) read(e), (!E[e].fi ? E[e].fi : E[e].se) = i; } cmax(ans, (int)ceil(sqrt(2 * (n - 1)))); if ((ans & 1) && ll(ans) * ans - 2 * (n - 1) + cnt < ans) ans++; cout << ans << '\n'; iota(id + 1, id + 1 + n, 1); sort(id + 1, id + 1 + n, [&](int x, int y) { return ssz(T[x]) < ssz(T[y]); }); int p = 1; cnt = 0; while (ssz(T[id[p + 1]]) == 1) p++; for (int i = n, j = p + 1; i >= j; i--) { ++cnt; sum[cnt] = ssz(T[id[i]]), val[id[i]] = cnt; while (j < i && sum[cnt] + ssz(T[id[j]]) <= ans) val[id[j]] = cnt, sum[cnt] += ssz(T[id[j++]]); assert(sum[cnt] <= ans); } int q = 1; For(i, 1, p) { while (sum[q] == ans) q++; assert(sum[q] < ans); sum[q]++, val[id[i]] = q; assert(sum[q] <= ans); assert(ssz(T[id[i]]) == 1); } // cerr << p << ' ' << cnt << ' ' << q << ' ' << ans << '\n'; cmax(cnt, q); assert(cnt <= ans); vector<int> U(ans); iota(beg2ed(U), 1); For(i, 1, n) for (int e : T[i]) G[val[i]].eb(e, i), G2[e].eb(val[i], i); For(i, 1, ans) { vector<int> tmp; assert(ssz(G[i]) <= ans); for (auto [e, x] : G[i]) { int j = rnd() % ssz(U); swap(U[j], U.back()); assert(!col.count({x, e})); tmp.eb(col[{x, e}] = U.back()), mp[i][U.back()] = {x, e}; U.pop_back(); } U.insert(U.end(), beg2ed(tmp)); } // cerr << ssz(G[2]) << ' ' << ans << '\n'; vector<int> todo; For(i, 1, n - 1) if (col[{G2[i][0].se, i}] == col[{G2[i][1].se, i}]) todo.eb(i), is_todo[i] = 1; // cerr << "T " << ssz(todo) << ' ' << is_todo[850] << '\n'; while (!todo.empty()) { int u = rnd() % ssz(todo), i = todo[u], j = rnd() & 1; // cerr << u << ' ' << i << ' ' << j << '\n'; assert(is_todo[i]); assert((col[{G2[i][0].se, i}] == col[{G2[i][1].se, i}])); vector<int> his; int ban = col[{G2[i][j].se, i}]; int ncol = rnd() % (ans - 1) + 1; if (ncol >= ban) ncol++, assert(ncol <= ans); assert(ncol != ban); while (1) { int to = G2[i][j].fi, x = G2[i][j].se; if (is_todo[i]) his.eb(i); if (col[{x, i}] != ban) break; // cerr << "A " << x << ' ' << i << ' ' << to << ' ' << col[{x, i}] << " // -> " // << ncol << '\n'; col[{x, i}] = ncol, mp[to].erase(ban); if (!mp[to].count(ncol)) { mp[to][ncol] = {x, i}; break; } pii e = exchange(mp[to][ncol], pii{x, i}); // cerr << "B " << e.fi << ' ' << e.se << ' ' << to << ' ' << col[e] // << " -> " << ban << '\n'; mp[to][ban] = e, col[e] = ban; i = e.se, j = G2[i][0] == pii{to, e.fi}; } for (int x : his) is_todo[x] = 0, todo.erase(find(beg2ed(todo), x)); } For(i, 1, n) { printf("%d ", val[i]); for (int e : T[i]) printf("%d ", col[{i, e}]); puts(""); } } void Main() { read(Tc); while (Tc--) solve(); } } // namespace signed main() { return Main(), 0; }