有向圖,兩人從起點 s 輪流移動飛機。離開節點後該節點不可再用。無法移動者負。判斷先手勝負,若勝輸出最小編號獲勝移動目標。
n ≤ 1000 可直接暴力 DFS 搜索遊戲樹。s 開始,嘗試每條出邊 u→v(按 v 編號升序,保證最小編號優先)。u 已用,遞歸判斷 v 是否為必敗。v 必敗,則 u 必勝,記錄答案 v 返回。v 均必勝,則 u 必敗。u 標記。#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int g[MAXN][MAXN], n, s, ans;
bool used[MAXN];
bool dfs(int u) {
for (int v = 1; v <= n; ++v) if (g[u][v] && !used[v]) {
used[u] = true;
if (!dfs(v)) { used[u] = false; ans = v; return true; }
used[u] = false;
}
return false;
}
int main() {
while (cin >> n >> s) {
memset(g,0,sizeof g); memset(used,0,sizeof used);
for (int i=1,u,v;i>u>>v; g[u][v]=g[v][u]=1;}
if (dfs(s)) printf("First player wins flying to airport %d\n", ans);
else puts("First player loses");
}
return 0;
}
O(n!) 理論最壞,但 n≤1000 實測極快(遊戲樹極小,因節點一次只能用一次)。O(n²) 存圖,O(n) 遞歸棧。used[] 標記當前路徑已用節點,回溯清除。true=當前玩家必勝,false=必敗。