#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