#include <stdio.h> #include <string.h> #define N 1005 bool map[N][N]; // 记录关系 bool end[N]; // 标记出度为0的点(终点) int sg[N]; bool ans[N]; // 标记所有要走的点(答案) int dp[N][2]; // 用于记忆化搜索,记录之后的路径是否能走(能为1,不能为0,-1代表还未走过),二维是因为要分先后手(先手走过,后手不一定) int n, m, f; int getSG(int k); // 获取SG值 bool dfs(int start, int k) // 深搜获得路径,start为当前点下标,k为输赢家标识,0表示输家,1表示赢家 { if(dp[start][k] != -1) // 检查之后的结点是否已经走过了 return dp[start][k] == 0 ? 0 : 1; int i; bool ls, ok = 0; if(k == 1){ // 赢家选择 for(i = start + 1; i <= n; i ++){ if(map[start][i] && sg[i] < (sg[i] ^ sg[start])){ if(end[i] == 0){ // 赢家走到终点,记录路径,返回1 ans[i] = 1; ok = 1; } ls = dfs(i, 0); // ls == 1 表示此路径可走通,标记路径上的点 if(ls){ ok = 1; ans[i] = 1; } } } } else{ // 输家选择, 因为必输,所以在先手选择正确的基础上,所以它的选择是随意的(但注意,这儿先手的选择不一定是对的) for(i = start + 1; i <= n; i ++) // 判断赢家选择是否正确,不正确直接返回0 if(map[start][i] && sg[i] < (sg[i] ^ sg[start])) return 0; for(i = start + 1; i <= n; i ++){ if(map[start][i]){ if(sg[i] < (sg[i] ^ sg[start])) // 输家走到终点,表示赢家有选择错误,停止搜索,返回0 return 0; ls = dfs(i, 1); if(ls){ // ls == 1 表示此路径可走通,标记路径上的点 ok = 1; ans[i] = 1; } } } } return dp[start][k] = ok; // 记录当前状态 } int main() { int x, y, i; while(scanf("%d%d%d", &n, &m, &f) != EOF){ memset(sg, -1, sizeof(sg)); // 初始化 memset(map, 0, sizeof(map)); memset(end, 0, sizeof(end)); memset(ans, 0, sizeof(ans)); memset(dp, -1, sizeof(dp)); while(m --){ scanf("%d%d", &x, &y); if(x == y) continue; if(x > y){ int temp = x; x = y; y = temp; } map[x][y] = 1; end[x] = 1; // 记录出度 } for(i = 1; i <= n; i ++){ if(end[i] == 0) // 出度为0的点为必败点,sg值为0 sg[i] = 0; } getSG(1); int win = (sg[1] != 0) ? f : (f + 1) % 2; printf("%d\n", win); // 输出赢家 ans[1] = 1; dfs(1, sg[1] == 0 ? 0 : 1); for(i = 1; i <= n; i ++){ // 输出路径,注意空格处理 if(ans[i]){ printf("%d", i); break; } } for(i = i + 1; i <= n; i ++){ if(ans[i]) printf(" %d", i); } printf("\n"); } return 0; } int getSG(int k) // 获取SG值 { if(sg[k] != -1) return sg[k]; bool hash[N]; memset(hash, 0, sizeof(hash)); for(int i = k + 1; i <= n; i ++){ if(!map[k][i]) continue; sg[i] = getSG(i); hash[sg[i]] = 1; } for(int j = 0; ; j ++) if(!hash[j]) return sg[k] = j; }
Tyvj p1371 蛇灵迷宫 (博弈 输出路径),布布扣,bubuko.com
原文地址:http://blog.csdn.net/tbl_123/article/details/25076259