在图论中,二分图(Bipartite Graph) 是指可以将所有节点分成 两个独立集合,并且同一个集合中的节点之间没有直接相连的无向图。判断图是否是二分图是许多应用的基础,例如:
- 任务调度:将任务分配给不同的执行组,避免冲突
- 资源分配:将用户与资源进行匹配,确保最优分配
- 冲突检测:在社交网络、推荐系统中检测是否存在冲突组
- 网络流优化:二分图匹配广泛用于最大流算法的优化
在本文中,我们将**基于 BFS(广度优先搜索)**实现 Java 版的二分图判定算法,并分析它的应用场景及优化方案。
1. 题目描述
给定一个无向图,判断它是否是二分图。
输入是一个邻接表 graph[i],表示与节点 i 相连的所有节点。
示例
Input: graph = {{1,3}, {0,2}, {1,3}, {0,2}}
Output: true
Explanation: 可以分成两个集合 {0,2} 和 {1,3},且没有内部连接。
2. Java 实现(BFS + 染色法)
代码实现
import java.util.*;
public class BipartiteGraphChecker {
private static final int COLOR_ONE = 1;
private static final int COLOR_TWO = -1;
public boolean isBipartite(int[][] graph) {
Map<Integer, Integer> visited = new HashMap<>();
for (int i = 0; i < graph.length; i++) {
if (!visited.containsKey(i)) {
if (!bfs(i, visited, graph)) {
return false;
}
}
}
return true;
}
private boolean bfs(int node, Map<Integer, Integer> visited, int[][] graph) {
Deque<Integer> queue = new ArrayDeque<>();
queue.offer(node);
visited.put(node, COLOR_ONE);
while (!queue.isEmpty()) {
Integer cur = queue.poll();
int curColor = visited.get(cur);
for (int neighbor : graph[cur]) {
if (visited.containsKey(neighbor)) {
if (visited.get(neighbor) != -curColor) {
return false;
}
} else {
queue.offer(neighbor);
visited.put(neighbor, -curColor);
}
}
}
return true;
}
public static void main(String[] args) {
BipartiteGraphChecker checker = new BipartiteGraphChecker();
int[][] graph = {{1, 3}, {0, 2}, {1, 3}, {0, 2}};
System.out.println(checker.isBipartite(graph)); // 输出 true
}
}
3. 代码解析
(1)思路:BFS + 染色法
-
我们使用
visited哈希表来存储每个节点的颜色:COLOR_ONE = 1COLOR_TWO = -1
-
采用 BFS 遍历图,初始时给定一个起始节点,并为其染色
COLOR_ONE。 -
遍历该节点的所有邻居:
- 若邻居未染色,则染成相反颜色并加入队列
- 若邻居已经染色,但颜色相同,则说明不是二分图,返回
false
(2)代码优化
- 使用
Deque<Integer>替代Queue<Integer>:提高队列操作性能 - 使用
HashMap<Integer, Integer>代替数组:适用于非连续节点编号的情况
4. 时间复杂度 & 空间复杂度
- **时间复杂度:**O(V + E),其中 V 是节点数,E 是边数,每个节点最多遍历一次,每条边最多遍历两次
- **空间复杂度:**O(V),存储
visited哈希表和queue
5. 二分图的实际应用
二分图广泛应用于计算机科学、网络结构和优化问题,下面是一些典型的应用场景:
| 应用领域 | 应用场景 | 二分图的作用 |
|---|---|---|
| 任务调度 | 任务-执行者匹配 | 任务与工作组形成二分图,确保任务合理分配 |
| 资源分配 | 用户-服务器匹配 | 通过二分图匹配实现最优资源分配 |
| 冲突检测 | 社交网络、推荐系统 | 发现对立用户组,防止冲突 |
| 最大流算法 | 网络流优化 | 通过最大匹配提高计算效率 |
| 数据库优化 | SQL 查询优化 | 通过二分图分割,优化索引计算 |
例如:
- 在 Kubernetes Pod 调度 中,可以将 Pod 和 可用节点 建立二分图,优化调度决策
- 在 DevOps 资源分配 中,服务器与任务调度可以建模为二分图匹配问题,提高资源利用率
6. 拓展:如何处理非连通图?
在现实应用中,图可能包含多个连通分量。
解决方案:
- 在
for循环中,遍历所有未访问的节点,确保所有连通分量都被遍历 - 这也是为什么代码中的
for循环遍历graph.length而不是仅检查graph[0]
7. 总结
🔹 二分图的核心思想:可以用 BFS 或 DFS 进行图染色,如果出现冲突则不是二分图
🔹 BFS 实现更适合大规模图,相比 DFS 更不容易栈溢出
🔹 应用广泛,在 任务调度、DevOps 资源分配、冲突检测 等场景下有重要作用