移棋子游戏
描述
给定一个有N个节点的有向无环图,图中某些节点上有棋子,两名玩家交替移动棋子。
玩家每一步可将任意一颗棋子沿一条有向边移动到另一个点,无法移动者输掉游戏。
对于给定的图和棋子初始位置,双方都会采取最优的行动,询问先手必胜还是先手必败。
输入
第一行,三个整数N,M,K,N表示图中节点总数,M表示图中边的条数,K表示棋子的个数。
接下来M行,每行两个整数X,Y表示有一条边从X出发指向Y。
接下来一行,K个空格间隔的整数,表示初始时,棋子所在的节点编号。
输出
若先手胜,输出win,否则输出lose。
输入样例 1
6 8 4 2 1 2 4 1 4 1 5 4 5 1 3 3 5 3 6 1 2 4 6
输出样例 1
win
提示
数据范围与提示:
对于全部数据,N≤2000,M≤6000,1≤K≤N。
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 2005;
vector<int> graph[MAXN];
int sg[MAXN];
bool visited[MAXN];
int calcSG(int node) {
if (visited[node]) return sg[node];
visited[node] = true;
vector<bool> mex(MAXN, false);
for (int next : graph[node]) {
mex[calcSG(next)] = true;
}
for (int i = 0; ; ++i) {
if (!mex[i]) {
sg[node] = i;
break;
}
}
return sg[node];
}
int main() {
int N, M, K;
cin >> N >> M >> K;
memset(sg, -1, sizeof(sg));
memset(visited, 0, sizeof(visited));
int x, y;
for (int i = 0; i < M; ++i) {
cin >> x >> y;
graph[x].push_back(y);
}
int totalSG = 0;
for (int i = 0; i < K; ++i) {
cin >> x;
totalSG ^= calcSG(x);
}
if (totalSG != 0) {
cout << "win" << endl;
} else {
cout << "lose" << endl;
}
return 0;
}