题意:一个有向无环图,制定M个点,每个点有一个石子。A,B两个玩家轮流移动这些石子(石子只能沿合法的边移动),最后没有石子可移的算输。
如果光看一个石子的话,这他妹的就是sg函数的定义啊。。。然后对整个图处理一下每个点的sg值。
对这M个点怎么处理,这么想吧。假设其中一个点为i,其sg值为sg[i] = a (a != 0)
那可以发现,i可以走向[0, a-1]的任意sg值,这相当与什么?相当与这里有一堆石子,共a个。。。。
M个点就是M堆石子,每堆石子的个数就是这个点的sg值。好吧Nim博弈出来了。。。
ps:有谁能把抑或傻逼的写成与,有谁能把标记数组写成全局变量???我能!脑子进屎了!
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%lld\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); typedef long long LL; const double eps = 1e-6; const double PI = acos(-1.0); const int inf = 0x1F1F1F1F; using namespace std; const int N = 1024; int n; int sg[N]; vector<int> vc[N]; void dfs(int r) { if(sg[r] != -1) return ; if(vc[r].size() == 0) { sg[r] = 0; return ; } bool vis[N] = {false}; for(int i = 0; i < int(vc[r].size()); ++i) { dfs(vc[r][i]); vis[sg[vc[r][i]]] = true; } for(int i = 0; i < n; ++i) { if(vis[i] == false) {sg[r] = i; break;} } } int main() { //Read(); int i, t, a, ans; while(~scanf("%d", &n)) { for(i = 0; i < n; ++i) { scanf("%d", &t); vc[i].clear(); while(t--) { scanf("%d", &a); vc[i].push_back(a); } sg[i] = -1; } for(i = 0; i < n; ++i) { if(sg[i] == -1) dfs(i); } while(scanf("%d", &t), t) { ans = 0; while(t--) { scanf("%d", &a); ans ^= sg[a]; // printf("%d %d\n", a, sg[a]); } if(ans) puts("WIN"); else puts("LOSE"); } } return 0; }