移棋子游戲
阿新 • • 發佈:2020-07-22
題目描述
給定一個有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; }