题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5299
题意:
在欧几里得平面上有n个圆,圆之间不会相交也不会相切,现在Alice和Bob玩游戏,两人轮流选择一个圆删除它和它包含的所有圆(Alice先手),在自己的轮次无圆可删判输,问你谁会赢得比赛
解:先将圆之间的关系抽象,转化为一个树图,然后套SG定理(WoW,我可不知道什么是SG定理
想详细了解的话,这里是和SG函数相关的东西:http://www.cnblogs.com/shjwudp/articles/4715439.html
然后又有SG定理(感觉不想关啊喂:
我们有如下定理: [定理] 叶子节点的 SG 值为 0; 中间节点的 SG 值为它的所有子节点的 SG 值加 1 后的异或和。
将圆关系抽象这个问题具体就是要查找,每个圆直接包含的圆,看了网上的题解,基本都是O(n^2),(有看起来是O(n logn)的
具体的请看代码理解吧:
1 /* 2 * Problem: 3 * Author: SHJWUDP 4 * Created Time: 2015/8/8 星期六 15:06:48 5 * File Name: 1006.cpp 6 * State: 7 * Memo: 8 */ 9 #include <iostream> 10 #include <cstdio> 11 #include <vector> 12 #include <cstring> 13 #include <algorithm> 14 15 using namespace std; 16 17 const int DIMENSION=2; 18 19 struct Point { 20 long long x[DIMENSION]; 21 }; 22 struct Circle { 23 Point o; 24 int r; 25 }; 26 struct Edge { 27 int u, v; 28 Edge(int u, int v):u(u), v(v) {} 29 }; 30 31 int n; 32 vector<Circle> arr; 33 vector<Edge> edges; 34 vector<vector<int> > G; 35 bool cmp(const Circle & a, const Circle & b) { 36 return a.r>b.r; 37 } 38 void init() { 39 edges.clear(); 40 G.assign(n+1, vector<int>(0)); 41 } 42 void addEdge(int u, int v) { 43 edges.push_back(Edge(u, v)); 44 G[u].push_back(edges.size()-1); 45 } 46 template<class T> T sqr(T x) { return x * x; } 47 bool judge(int a, int b) { 48 if(a==n || b==n) return 1; 49 int d=0; 50 for(int k=0; k<DIMENSION; k++) { 51 d+=sqr(arr[a].o.x[k]-arr[b].o.x[k]); 52 } 53 int r=max(arr[a].r, arr[b].r); 54 return r*r>=d; 55 } 56 void fin(int u, int x) { 57 for(int i : G[u]) { 58 Edge & e=edges[i]; 59 if(judge(x, e.v)) { 60 fin(e.v, x); 61 return; 62 } 63 } 64 addEdge(u, x); 65 } 66 int dfs(int u) { 67 int res=0; 68 for(int i : G[u]) { 69 Edge & e=edges[i]; 70 res^=1+dfs(e.v); 71 } 72 return res; 73 } 74 int main() { 75 #ifndef ONLINE_JUDGE 76 freopen("in", "r", stdin); 77 //freopen("out", "w", stdout); 78 #endif 79 int T; 80 scanf("%d", &T); 81 while(T--) { 82 scanf("%d", &n); 83 arr.resize(n); 84 for(int i=0; i<n; i++) { 85 Circle & c=arr[i]; 86 for(int k=0; k<DIMENSION; k++) { 87 scanf("%I64d", &c.o.x[k]); 88 } 89 scanf("%d", &c.r); 90 } 91 sort(arr.begin(), arr.end(), cmp); 92 93 init(); 94 for(int i=0; i<n; i++) fin(n, i); 95 puts(dfs(n)?"Alice":"Bob"); 96 } 97 return 0; 98 }