給定無向圖(n 點 m 邊,無重邊自環),從任意點出發,每秒移動到相鄰點(可走重複邊,不可原地停留)。問是否存在某時刻 t,使得所有 n 個點都可能被到達。等價於:圖是否連通且存在奇環。
int color[MAXN]; // -1 未訪問,0/1 兩色
bool hasOddCycle = false;
bool dfs(int u, int c) {
color[u] = c;
for (int v : adj[u]) {
if (color[v] == -1) {
if (!dfs(v, c^1)) return false;
} else if (color[v] == c) {
hasOddCycle = true;
return false;
}
}
return true;
}
queueq; color[s] = 0; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (int v : adj[u]) { if (color[v] == -1) { color[v] = color[u]^1; q.push(v); } else if (color[v] == color[u]) { hasOddCycle = true; break; } } }
維護 val[x] 表示 x 到根的奇偶距離(mod 2)。合併邊 (u,v) 時:
val[root_u] = val[u] ^ val[v] ^ 1(邊長為 1,奇偶翻轉)。val[u] ^ val[v] 是否為 1,否則發現奇環。int find(int x) {
if (fa[x] != x) {
int p = fa[x];
fa[x] = find(fa[x]);
val[x] ^= val[p];
}
return fa[x];
}
void unite(int u, int v) {
int fu = find(u), fv = find(v);
if (fu != fv) {
fa[fu] = fv;
val[fu] = val[u] ^ val[v] ^ 1;
} else if ((val[u] ^ val[v]) == 0) hasOddCycle = true;
}
// 讀入圖 // 初始化並查集 / color 數組 // 遍歷所有邊 unite / dfs // 檢查連通性:所有點 find 根是否相同 // 輸出:hasOddCycle && connected ? "YES" : "NO"
DFS/BFS O(n+m);並查集 O((n+m) α(n))。三種方法均滿足 n,m ≤ 10⁵。