Description
Suppose we have a directed acyclic graph with some number of stones at each node. Two players take turns moving a stone from any node to one of its neighbours, following a directed edge. The player that cannot move any stone loses the game. Note that multiple stones may occupy the same node at any given time.
The test case is terminated by n more integers s0,..., sn-1 (one per line), where si represents the number of stones that are initially placed on node i ( 0si1000).
Each test case is followed by a blank line, and input is terminated by a line containing `0 0' which should not be processed.
4 3 0 1 1 2 2 3 1 0 0 0 7 7 0 1 0 2 0 4 2 3 4 5 5 6 4 3 1 0 1 0 1 0 0 0 0
First Second 有一個DAG(有向五環圖),每個結點上都有一些石子。兩個玩家輪流把一個石頭從一個結點沿著從此點出發的任意一條有向邊移向相鄰結點。不能移動的玩家算輸掉游戲。注 意,在同一個時刻一個節點上可以有任意的石頭。 思路:注意到,各個石頭的狀態的是完全獨立的,所以這個游戲可以看做每個石頭所形成的游戲的和。對於每一個石頭,它的狀態x就是所在的結點編號,如果此結點已經沒有出發的邊,則既是先手必敗的狀態,否則後續狀態就是相鄰結點的SG值集合。
需要注意的是,對於在同一個結點來說,其上的石頭如果個數為奇數,則當成1個石頭即可;如果為偶數,可以忽略不計。這是由異或運算的性質決定的。
#include#include #include #include #include using namespace std; const int maxn = 10005; int n, m, sg[maxn]; vector g[maxn]; int SG(int u) { if (sg[u] != -1) return sg[u]; int vis[maxn]; memset(vis, 0, sizeof(vis)); for (int i = 0; i < g[u].size(); i++) { int tmp = SG(g[u][i]); vis[tmp] = 1; } for (int j = 0; ; j++) if (!vis[j]) { sg[u] = j; break; } return sg[u]; } int main() { int u, v; while (scanf("%d%d", &n, &m) != EOF && n+m) { memset(sg, -1, sizeof(sg)); for (int i = 0; i < maxn; i++) g[i].clear(); for (int i = 0; i < m; i++) { scanf("%d%d", &u, &v); g[u].push_back(v); } for (int i = 0; i < n; i++) sg[i] = SG(i); int ans = 0, u; for (int i = 0; i < n; i++) { scanf("%d", &u); if (u & 1) ans ^= sg[i]; } printf("%s\n", ans ? "First": "Second"); } return 0; }