結果
| 問題 |
No.2800 Game on Tree Inverse
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-06-29 05:45:55 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 346 ms / 4,000 ms |
| コード長 | 6,190 bytes |
| コンパイル時間 | 1,464 ms |
| コンパイル使用メモリ | 124,224 KB |
| 実行使用メモリ | 88,704 KB |
| 最終ジャッジ日時 | 2024-06-29 05:46:14 |
| 合計ジャッジ時間 | 18,426 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 64 |
ソースコード
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
// !!!Watch out for stack overflow!!!
// Meldable
// 0 for null, ts[0] = T()
// Manages the number of elements (as a set).
template <class T> struct Seg {
static constexpr int NUM_NODES = 1 << 23;
int h;
int nodesLen;
int nxt[NUM_NODES][2];
T ts[NUM_NODES], lz[NUM_NODES];
void init(int h_) {
h = h_;
nodesLen = 1;
nxt[0][0] = nxt[0][1] = 0;
ts[0] = T();
lz[0] = T();
}
int newNode() {
assert(nodesLen < NUM_NODES);
const int u = nodesLen++;
nxt[u][0] = nxt[u][1] = 0;
ts[u] = T(0);
lz[u] = T(0);
return u;
}
// u: height e
void ch(int e, int u, T t) {
if (u) {
if (e && (t >> (e - 1) & 1)) swap(nxt[u][0], nxt[u][1]);
lz[u] ^= t;
}
}
void ch(int u, T t) {
ch(h, u, t);
}
// u: height (e+1)
void push(int e, int u) {
if (lz[u]) {
ch(e, nxt[u][0], lz[u]);
ch(e, nxt[u][1], lz[u]);
lz[u] = 0;
}
}
void pull(int u) {
ts[u] = ts[nxt[u][0]] + ts[nxt[u][1]];
}
int build(T a) {
assert(0 <= a); assert(a < T(1) << h);
const int u = nodesLen;
for (int e = 0; e <= h; ++e) ts[newNode()] = T(1);
for (int e = 0; e < h; ++e) nxt[u + (e + 1)][a >> e & 1] = u + e;
return u + h;
}
T mex(int u) {
if (ts[u] == T(1) << h) return T(1) << h;
T a = 0;
for (int e = h; --e >= 0; ) {
push(e, u);
if (ts[nxt[u][0]] == T(1) << e) {
a |= T(1) << e;
u = nxt[u][1];
} else {
u = nxt[u][0];
}
}
return a;
}
// Frees v.
int meld(int e, int u, int v) {
if (!u) return v;
if (!v) return u;
if (!e) {
ts[u] |= ts[v];
return u;
}
--e;
push(e, u);
push(e, v);
nxt[u][0] = meld(e, nxt[u][0], nxt[v][0]);
nxt[u][1] = meld(e, nxt[u][1], nxt[v][1]);
pull(u);
return u;
}
int meld(int u, int v) {
return meld(h, u, v);
}
// Does not push.
void print(int e, T a, int u) {
if (!u) return;
cerr << string(2 * (h - e), ' ') << u << " [" << a << ", " << (a | T(1) << e) << ") " << ts[u] << " " << lz[u] << endl;
if (!e) return;
--e;
print(e, a, nxt[u][0]);
print(e, a | T(1) << e, nxt[u][1]);
}
void print(int u) {
if (!u) cerr << "[Seg::print] null" << endl;
print(h, T(0), u);
}
// Pushes
string toString(int e, T a, int u) {
if (!u) return "";
if (!e) return to_string(a) + ",";
--e;
push(e, u);
return toString(e, a, nxt[u][0]) + toString(e, a | T(1) << e, nxt[u][1]);
}
string toString(int u) {
return "{" + toString(h, T(0), u) + "}";
}
};
int N;
vector<int> A, B;
vector<vector<int>> graph;
pair<int, vector<int>> slow(int u, int p) {
int sum = 0;
vector<int> xs{0};
for (const int v : graph[u]) if (p != v) {
const auto res = slow(v, u);
sum ^= res.first;
for (const int x : res.second) xs.push_back(x ^ res.first);
}
for (int &x : xs) x ^= sum;
sort(xs.begin(), xs.end());
xs.erase(unique(xs.begin(), xs.end()), xs.end());
for (int x = 0; ; ++x) {
if (!(x < (int)xs.size() && xs[x] == x)) {
cerr<<"[slow] "<<u<<": "<<x<<" "<<xs<<endl;
return make_pair(x, xs);
}
}
}
vector<int> dp;
Seg<int> seg;
int dfs(int u, int p) {
int sum = 0;
int ret = seg.build(0);
for (const int v : graph[u]) if (p != v) {
const int res = dfs(v, u);
sum ^= dp[v];
// cerr<<__LINE__<<": "<<u<<" <- "<<v<<": "<<seg.toString(res)<<endl;//seg.print(ret);
seg.ch(res, dp[v]);
// cerr<<__LINE__<<": "<<u<<" <- "<<v<<": "<<seg.toString(res)<<endl;//seg.print(ret);
ret = seg.meld(ret, res);
// cerr<<__LINE__<<": "<<u<<" <- "<<v<<": "<<seg.toString(ret)<<endl;//seg.print(ret);
}
seg.ch(ret, sum);
dp[u] = seg.mex(ret);
// cerr<<"[dfs] "<<u<<": "<<dp[u]<<" "<<seg.toString(ret)<<endl;//seg.print(ret);
return ret;
}
vector<int> ans;
void DFS(int u, int p, int now) {
now ^= dp[u];
for (const int v : graph[u]) if (p != v) now ^= dp[v];
if (!now) {
ans.push_back(u);
}
for (const int v : graph[u]) if (p != v) {
DFS(v, u, now);
}
now ^= dp[u];
for (const int v : graph[u]) if (p != v) now ^= dp[v];
}
int main() {
for (; ~scanf("%d", &N); ) {
A.resize(N - 1);
B.resize(N - 1);
for (int i = 0; i < N - 1; ++i) {
scanf("%d%d", &A[i], &B[i]);
--A[i];
--B[i];
}
graph.assign(N, {});
for (int i = 0; i < N - 1; ++i) {
graph[A[i]].push_back(B[i]);
graph[B[i]].push_back(A[i]);
}
int E;
for (E = 0; !(N < 1 << E); ++E) {}
seg.init(E);
dp.assign(N, -1);
dfs(0, -1);
if (dp[0]) {
ans.clear();
DFS(0, -1, dp[0]);
sort(ans.begin(), ans.end());
puts("Alice");
printf("%d\n", (int)ans.size());
for (int h = 0; h < (int)ans.size(); ++h) {
if (h) printf(" ");
printf("%d", ans[h] + 1);
}
puts("");
} else {
puts("Bob");
}
#ifdef LOCAL
slow(0,-1);
#endif
}
return 0;
}