移棋子游戏
题目描述
给定一个有N个节点的有向无环图,图中某些节点上有棋子,两名玩家交替移动棋子。
玩家每一步可将任意一颗棋子沿一条有向边移动到另一个点,无法移动者输掉游戏。
对于给定的图和棋子初始位置,双方都会采取最优的行动,询问先手必胜还是先手必败。
玩家每一步可将任意一颗棋子沿一条有向边移动到另一个点,无法移动者输掉游戏。
对于给定的图和棋子初始位置,双方都会采取最优的行动,询问先手必胜还是先手必败。
输入描述:
第一行,三个整数N,M,K,N表示图中节点总数,M表示图中边的条数,K表示棋子的个数。
接下来M行,每行两个整数X,Y表示有一条边从X出发指向Y。
接下来一行,K个空格间隔的整数,表示初始时,棋子所在的节点编号。
输出描述:
若先手胜,输出win,否则输出lose。
输入
6 8 4 2 1 2 4 1 4 1 5 4 5 1 3 3 5 3 6 1 2 4 6
输出
win
备注:
对于全部数据,N \leq 2000,M \leq 6000,1 \leq K \leq NN≤2000,M≤6000,1≤K≤N。
// SG函数模板题 #include<bits/stdc++.h> using namespace std; const int MAXM = 1e4 + 7; const int MAXN = 2e3 + 7; int head[MAXM], ver[MAXM], nex[MAXM], vis[MAXM], sg[MAXM], tot; int N, M, K; void add(int x, int y) { ver[++tot] = y; nex[tot] = head[x]; head[x] = tot; } void dfs(int x) { if (vis[x]) return; vis[x] = 1; int up = 0; int mark[MAXN] = {0}; for (int i = head[x]; i; i = nex[i]) { dfs(ver[i]); up = max(up, sg[ver[i]]); mark[sg[ver[i]]] = 1; } for (int i = 0; i <= up + 1; i++) { if (!mark[i]) { sg[x] = i; break; } } } void getSG() { for (int i = 1; i <= N; i++) { if (!vis[i]) dfs(i); } } int main() { int x, y; cin >> N >> M >> K; for (int i = 1; i <= M; i++) { cin >> x >> y; add(x, y); } getSG(); int ans = 0; for (int i = 1; i <= K; i++) { cin >> x; ans ^= sg[x]; } if (ans) cout << "win" << endl; else cout << "lose" << endl; return 0; }

浙公网安备 33010602011771号