您的位置:首页 > 其它

【Spoj COT3】SG函数 Trie启发式合并

2015-11-02 08:12 405 查看
给一颗有黑白点的有根树,每次可以选一个白点并将其到根的路径染黑,问先手是否必胜以及第1步的可能选择。

子树间相互独立,用Trie维护一个子树操作一次可达SG值,这个用Trie启发式合并可求,需要打标记。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define Rep(i, x, y) for (int i = x; i <= y; i ++)
#define Dwn(i, x, y) for (int i = x; i >= y; i --)
#define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex)
#define u t[x]
#define o t[y]
#define Lc t[u.lc]
#define Rc t[u.rc]
using namespace std;
typedef long long LL;
const int N = 100005;
struct Edge { int y, nex; } g[N * 2];
struct arr { int lc, rc, lz; bool f; } t[N * 70];
int n, pos
, sz, tsz, ans
, az, q, f
, ro
, c
;
void Init(int x, int y) { g[++ sz] = (Edge) { y, pos[x] }, pos[x] = sz; }
void PD(int x, int dt) {
if (!x || !u.lz) return ;
if (u.lz & (1 << dt-1)) swap(u.lc, u.rc);
Lc.lz ^= u.lz, Rc.lz ^= u.lz; u.lz = 0;
}
void Merge(int &x, int y, int dt) {
if (!x || !y) { x += y; return ; }
if (!dt) return ;
PD(x, dt), PD(y, dt);
Merge(u.lc, o.lc, dt - 1), Merge(u.rc, o.rc, dt - 1);
u.f = Lc.f & Rc.f;
}
int Find(int x, int dt) {
if (!dt) return 0;
PD(x, dt);
if (Lc.f) return Find(u.rc, dt - 1) + (1 << dt-1);
else return Find(u.lc, dt - 1);
}
void Add(int &x, int dt) {
if (!x) x = ++ tsz;
if (!dt) { u.f = 1; return ; }
PD(x, dt);
if (q & (1 << dt-1)) Add(u.rc, dt - 1); else Add(u.lc, dt - 1);
u.f = Lc.f & Rc.f;
}
void Dfs(int x, int ft) {
int z = 0;
RepE(i, x) {
int y = g[i].y; if (y == ft) continue ;
Dfs(y, x), z ^= f[y];
}
RepE(i, x) {
int y = g[i].y; if (y == ft) continue ;
t[ ro[y] ].lz ^= (z ^ f[y]); Merge(ro[x], ro[y], 17);
}
if (c[x]) q = z, Add(ro[x], 17); f[x] = Find(ro[x], 17);
}
void Print(int x, int ft, int z) {
int r = 0;
RepE(i, x) if (g[i].y != ft) r ^= f[ g[i].y ];
RepE(i, x) {
int y = g[i].y; if (y == ft) continue ;
Print(y, x, z ^ r ^ f[y]);
}
if (c[x] && (z ^ r) == 0) ans[++ az] = x;
}
int main()
{
scanf ("%d", &n);
Rep(i, 1, n) scanf ("%d", &c[i]), c[i] ^= 1;
Rep(i, 1, n - 1) {
int x, y;
scanf ("%d%d", &x, &y), Init(x, y), Init(y, x);
}
Dfs(1, 1);
if (!f[1]) { puts("-1"); return 0; }
Print(1, 1, 0);
sort(ans+1, ans+az+1);
Rep(i, 1, az) printf("%d\n", ans[i]);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: