1.流程
isBipartite()
│
├─ cur = 0
│ │
│ ├─ team[0] == 0
│ │
│ ├─ team[0] = +1 ← 第一群起點,任意先放 +1
│ │
│ └─ dfs(0)
│ │
│ ├─ next = 1
│ ├─ team[1] == 0
│ ├─ team[1] = -team[0] = -1
│ ├─ dfs(1)
│ └─ 無衝突 → true
│
├─ cur = 1
│ └─ team[1] = -1,已分隊 → 跳過
│
├─ cur = 2
│ │
│ ├─ team[2] == 0 ← 發現第二群
│ ├─ team[2] = +1 ← 新的一群可重新任意選 +1
│ └─ dfs(2)
│ │
│ ├─ next = 3
│ ├─ team[3] == 0
│ ├─ team[3] = -team[2] = -1
│ ├─ dfs(3)
│ └─ 無衝突 → true
│
├─ cur = 3
│ └─ team[3] = -1,已分隊 → 跳過
│
└─ 所有 component 都沒有衝突
↓
return true
Connected Component(連通元件) 整張 Graph
互相走得到的一群節點 所有 component 合起來
0—1—2 0—1—2 3—4
DFS 一次能處理一整群 不一定能處理全部
DFS 只能沿著 edge 走 不相連的另一群走不到
dfs() isBipartite() 外層for
3.DFS 做完一群 → 外層再找下一群 → 所有群完成才代表整張 Graph 完成。
DFS 只是流程圖裡「走完一個 Connected Component」的其中一個步驟。
看到 next
↓
team[next] == 0?
┌──────┴──────┐
是 否
↓ ↓
還沒分隊 已經分隊
↓ ↓
放到相反隊 跟 cur 同隊嗎?
↓ ├─ 是 → false
繼續 DFS └─ 否 → OK,繼續
5.只有「直接有 edge 相連」的兩個節點才必須一正一負;不同 Connected Component 之間互不影響。
class Solution {
public:
// DFS:把相連節點分到相反隊伍
bool dfs(vector<vector<int>>& link, vector<int>& team, int cur) {
for (int next : link[cur]) { // 看 cur 連到哪些 next
if (team[next] == 0) { // next 還沒分隊
team[next] = -team[cur]; // 放到 cur 的相反隊
if (!dfs(link, team, next)) // 從 next 繼續 DFS
return false;
}
else if (team[next] == team[cur]) { // 相連兩點同隊
return false;
}
}
return true; // 這一群沒有衝突
}
bool isBipartite(vector<vector<int>>& link) {
int n = link.size();
vector<int> team(n, 0); // 0=未分隊,1=A,-1=B
// Graph 可能有多個 Connected Component
for (int cur = 0; cur < n; ++cur) {
if (team[cur] == 0) { // 找到還沒處理的新一群
team[cur] = 1; // 先放 A 隊
if (!dfs(link, team, cur))
return false;
}
}
return true;
}
};