【Spoj COT3】SG函数 Trie启发式合并
2015-11-02 08:12
405 查看
给一颗有黑白点的有根树,每次可以选一个白点并将其到根的路径染黑,问先手是否必胜以及第1步的可能选择。
子树间相互独立,用Trie维护一个子树操作一次可达SG值,这个用Trie启发式合并可求,需要打标记。
子树间相互独立,用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; }
相关文章推荐
- visual studio 2015 调试程序
- huffman 编码
- HTTP通信过程底层实现原理
- SSH框架+EL表达式—jsp跨界面传值显示
- 对DataTable进行排序(sort)
- 冰淇淋的爱音乐播放器
- 5-24 树种统计 (25分)
- 各类经典dp问题分讲(HDU 2084、HDU 1003、HDU 1176)
- 多线程之指令重排序
- 1078 最小生成树 -- prime
- ORACLE将表中的数据恢复到某一个时间点
- Spring rest 启动报错的一种可能性
- JSP EL表达式 获得 request的GET/POST方法
- 去除 MyEclipse updating index
- 【bzoj1576】[Usaco2009 Jan]安全路经Travel
- AFN网络请求封装(MRC模式, 若是ARC模式 需添加 -fno-objc-arc )
- Touch Handling in Cocos2D 3.x(二)
- Touch Handling in Cocos2D 3.x(二)
- Touch Handling in Cocos2D 3.x(二)
- 近期总结:generator-web,前端自动化构建的解决方案