染色法判断二分图(二部图)
染色法判定二部图基本思想:
1、任意选择一个节点,将其染成红色
2、循环操作:将红色节点的邻居染成蓝色,将蓝色节点的邻居染成红色
3、若过程中发现任意一节点与其邻居的颜色相同,则该图不是二部图,否则是二部图。
核心代码:
int 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]) {if (!dfs(j, 3 - c)) return 0;}else if (color[j] == c) return 0;}return 1;
}
二分图最大匹配
372. 棋盘覆盖(匈牙利算法,二分图最大匹配)-CSDN博客
861. 二分图的最大匹配(匈牙利算法, 二分图的最大匹配)-CSDN博客
“任意两条边都没有公共端点”的边的集合被称为图的一组匹配,在二分图中,包含边数最多的一组匹配被称为二分图的最大匹配。
对于任意一组匹配 S ( S 是一个边集),属于 S 的边被称为“匹配边”, 不属于 S 的边被称为“非匹配边” 。匹配边的端点被称为“匹配点”, 其他节点被称为“非匹配点”。 如果在二分图中存在一条连接两个非匹配点的路径 path , 使得非匹配边与匹配边在 path 上交替出现,那么称 path 是匹配 S 的增广路, 也称交错路。
增广路显然具有以下性质:
1.长度 len 是奇数。
2.路径上第1,3,5,……, len 条边是非匹配边,第 2,4,6,… ,len-1 条边是匹配边。
正因为以上性质,如果我们把路径上所有边的状态取反,原来的匹配边变成非匹配的,原来的非匹配边变成匹配的,那么得到的新的边集 S` 仍然是一组匹配,并且匹配边数增加了1。进一步可以得到推论:
二分图的一组匹配 S 是最大匹配,当且仅当图中不存在 S 的增广路。
匈牙利算法
1. **初始化:** 对于给定的二分图,将每个顶点的标记初始化为未匹配。
2. **从左侧开始:** 从二分图的左侧开始,对每个未匹配的顶点尝试找到增广路径。
3. **寻找增广路径:** 从当前未匹配的左侧顶点开始,尝试沿着未匹配的边找到增广路径。增广路径是一条交替经过未匹配边和已匹配边的路径。
4. **增广路径存在:** 如果找到增广路径,则根据增广路径更新匹配关系。更新的方式是将路径上的已匹配边变为未匹配,未匹配边变为已匹配。
5. **增广路径不存在:** 如果无法找到增广路径,说明当前左侧顶点已经无法找到匹配,此时需要尝试调整之前的匹配,即修改之前已匹配的边。
6. **调整匹配:** 通过调整匹配,使得右侧的顶点重新可以匹配。具体做法是选择已匹配边中的一条,然后尝试寻找增广路径。
7. **重复步骤2-6:** 重复进行步骤2到步骤6,直到无法找到更多的增广路径为止。
8. **结束:** 当无法再找到增广路径时,算法结束。此时已经找到了二分图的最大匹配。
核心代码:
主函数中的代码:
for (int i = 1; i <= n1; i++) {memset(st, 0, sizeof st);if (find(i)) {ret++;}}
函数
int find(int u) {for (int i = h[u]; i != -1;i=ne[i]) {int j = e[i];if (!st[j]) {st[j] = 1;//如果点 j 还没有被匹配,或者find(match[j])能为与j匹配的点找到新的下家if (match[j] == 0 || find(match[j])) {match[j] = u;return 1;}}}return 0;
}