染色法判定二分图
什么是二分图:
若将图的节点可以分为两个集合 u 和 v ,所有节点都只和另一个集合的节点连通,不和所在节点存在边,那么该图被称为是一个二分图
下面的则不是一个二分图
染色法判定二分图模版题
给定一个 n n n 个点 m m m 条边的无向图,图中可能存在重边和自环。
请你判断这个图是否是二分图。
输入格式
第一行包含两个整数 n n n 和 m m m。
接下来 m m m 行,每行包含两个整数 u u u 和 v v v,表示点 u u u 和点 v v v 之间存在一条边。
输出格式
如果给定图是二分图,则输出 Yes
,否则输出 No
。
数据范围
1 ≤ n , m ≤ 1 0 5 1 \le n,m \le 10^5 1≤n,m≤105
输入样例:
4 4
1 3
1 4
2 3
2 4
输出样例:
Yes
算法所需空间:
- 邻接表,作用为存储无向图
- color数组,表示节点的染色状态(这里规定 0为未染色状态,1为一种颜色,2为另一种颜色)
算法流程:
- 利用dfs或bfs进行染色
- 若某个节点连通的节点和当前节点颜色一样,则说明不是二分图;若未染色,则染当前节点颜色的另一个颜色
代码:
准备阶段:
- 包含可能需要的头文件
- 定义题目所给的常量,N为最大节点数,M为最大有向边 数。
由于题目中的n 和 m 最大都是 1e5,所以M = N * 2;(注意:M是题目中m的2倍,不是n的2倍,只不过该题目刚好n和m相等)
算法所需空间:
主函数代码:
n 和 m 害怕其他函数需要用到,所以作为成员变量
为什么将所有点都试图染色?
因为二分图不一定连通
dfs(int u, int c)的函数功能是,从u节点开始染色,u节点初始染的颜色为 c
若染色成功返回true,失败返回false
函数体如下:
为什么是3 - c ?
1和2为两种染色状态,3 - c无论是那种状态,都可以切换成另一种状态
总结:
算法空间:
- 邻接表
- 染色状态数组
染色算法流程:(利用dfs)
- 给当前节点染色
- 遍历其连通点,若其染色与当前节点相同,则染色宣告失败;若未染色,若以连通节点为开始染另一个颜色失败,则也染色失败
易错点:
- 定义常量M时,由于是无向图,所以需要时题目中边的最大数量的二倍
- 主函数中要尝试给所有点进行染色,因为有可能该图未连通
- dfs 函数中 3 - c的使用,这样可以方便转换染的颜色