二分图
- 染色法:时间复杂度 \(O(n+m)\)
- 匈牙利算法:时间复杂度最坏 \(O(mn)\),但实际运行时间一般远小于 \(O(mn)\)
染色法
二分图的定义:有两顶点集且图中每条边的的两个顶点分别位于两个顶点集中,每个顶点集中没有边直接相连接的图(图中点通过移动能分成左右两部分,左侧的点只和右侧的点相连,右侧的点只和左侧的点相连)
染色法可以用来判断一个图是不是二分图。
定理:一个图是二分图当且仅当图中不含奇数环(边数为奇数的环)。
- 开始对任意一未染色的顶点染色。
- 判断其相邻的顶点中,若未染色则将其染上和相邻顶点不同的颜色。
- 若已经染色且颜色和相邻顶点的颜色相同则说明不是二分图,若颜色不同则继续判断。
- 通过DFS或BFS进行搜索。
例题:染色法判定二分图
代码模板:
| /*
1. color数组初始化为0,被访问的点的颜色为1或2
2. 进入u,对u点染色
3. 枚举u的邻点v
(1)若v未访问,走进去,若返回有奇环,则一路返回有奇环
(2)若v已访问且v的颜色与u的颜色相同,则返回有奇环
4. 枚举完u的邻点,没有发现有奇环,则返回没有奇环
*/
int n; //n为点数
int h[N], e[M], ne[M], idx; //邻接表存储图
int color[N]; //表示每个点的颜色,-1表示未染色,0表示白色,1表示黑色
// 参数:u表示当前节点,c表示当前点的颜色
bool dfs(int u, int c) {
color[u] = c;
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (color[j] == -1) {
if (!dfs(j, !c)) return false;
} else if (color[j] == c) return false;
}
return true;
}
bool check() {
memset(color, -1, sizeof color);
bool flag = true;
for (int i = 1; i <= n; i++) {
if (color[i] == -1) {
if (!dfs(i, 0)) {
flag = false;
break;
}
}
}
return flag;
}
|
匈牙利算法
例题:二分图的最大匹配