/* *State: Accepted 8104K 485MS C++ 1428B *题目大意: * 两个人在一个有向五环图上面走棋子,每次只能走一步,最后谁 * 没有棋子可走就败,然后棋子可以重叠,并且有n个棋子。要求判断 * 先手的胜负。 *解题思路: * 一开始没有思路,后来试着用sg去推,推出sg了。 *解题感想: * 用了静态邻接表之后,快了,但是此题不明显。 * 果然,静态邻接表的边的数目要把握好,RE了两次。 */
View Code
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 const int MAX = 1024; 6 int sg[MAX], head[MAX], cnt; 7 typedef struct node_ 8 { 9 int v; 10 int next; 11 }N; 12 N edge[1000 * MAX];//注意边的数目 13 14 void addEdge(int u, int v) 15 { 16 edge[cnt].v = v; 17 edge[cnt].next = head[u]; 18 head[u] = cnt++; 19 } 20 21 int get_sg(int n) 22 { 23 if(sg[n]) 24 return sg[n]; 25 26 if(head[n] == -1) 27 return sg[n] = 0; 28 29 int vst[MAX] = {0}, h = 0; 30 for(int f = head[n]; f != -1; f = edge[f].next) 31 { 32 int son = edge[f].v, tmp; 33 tmp = get_sg(son); 34 vst[tmp] = 1; 35 } 36 for(int i = 0; i < MAX; i++) 37 { 38 if(!vst[i]) 39 return sg[n] = i; 40 } 41 } 42 43 void init() 44 { 45 memset(head, -1, sizeof(head)); 46 cnt = 0; 47 } 48 49 int main(void) 50 { 51 #ifndef ONLINE_JUDGE 52 freopen("in.txt", "r", stdin); 53 #endif 54 55 int n; 56 while(scanf("%d", &n) == 1) 57 { 58 init(); 59 memset(sg, 0, sizeof(sg)); 60 int in[MAX] = {0}; 61 for(int i = 0; i < n; i++) 62 { 63 int m; 64 scanf("%d", &m); 65 for(int j = 0; j < m; j++) 66 { 67 int t; 68 scanf("%d", &t); 69 addEdge(i, t); 70 in[t]++; 71 } 72 } 73 for(int i = 0; i < n; i++) 74 { 75 if(!in[i])//入度为0的都要搜一遍 76 get_sg(i); 77 } 78 int a; 79 while(scanf("%d", &a), a) 80 { 81 int yihuo = 0; 82 for(int i = 0; i < a; i++) 83 { 84 int t; 85 scanf("%d", &t); 86 yihuo ^= sg[t]; 87 } 88 if(!yihuo) 89 printf("LOSE\n"); 90 else 91 printf("WIN\n"); 92 } 93 } 94 return 0; 95 }