\color{green}{<–画图不易,点下这里赞一下吧}
什么叫二分图
-
有两顶点集且图中每条边的的两个顶点分别位于两个顶点集中,每个顶点集中没有边直接相连接!
-
说人话的定义:图中点通过移动能分成左右两部分,左侧的点只和右侧的点相连,右侧的点只和左侧的点相连。
-
下图就是个二分图:
{:weith=250 height=250}
- 下图不是个二分图:
如果判断一个图是不是二分图?
-
开始对任意一未染色的顶点染色。
-
判断其相邻的顶点中,若未染色则将其染上和相邻顶点不同的颜色。
-
若已经染色且颜色和相邻顶点的颜色相同则说明不是二分图,若颜色不同则继续判断。
-
bfs和dfs可以搞定!
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010 * 2;
int e[N], ne[N], idx;//邻接表存储图
int h[N];
int color[N];//保存各个点的颜色,0 未染色,1 是红色,2 是黑色
int n, m;//点和边
void add(int a, int b)//邻接表插入点和边
{
e[idx] = b, ne[idx]= h[a], h[a] = idx++;
}
bool dfs(int u, int c)//深度优先遍历
{
color[u] = c;//u的点成 c 染色
//遍历和 u 相邻的点
for(int i = h[u]; i!= -1; i = ne[i])
{
int b = e[i];
if(!color[b])//相邻的点没有颜色,则递归处理这个相邻点
{
if(!dfs(b, 3 - c)) return false;//(3 - 1 = 2, 如果 u 的颜色是2,则和 u 相邻的染成 1)
//(3 - 2 = 1, 如果 u 的颜色是1,则和 u 相邻的染成 2)
}
else if(color[b] && color[b] != 3 - c)//如果已经染色,判断颜色是否为 3 - c
{
return false;//如果不是,说明冲突,返回
}
}
return true;
}
int main()
{
memset(h, -1, sizeof h);//初始化邻接表
cin >> n >> m;
for(int i = 1; i <= m; i++)//读入边
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
for(int i = 1; i <= n; i++)//遍历点
{
if(!color[i])//如果没染色
{
if(!dfs(i, 1))//染色该点,并递归处理和它相邻的点
{
cout << "No" << endl;//出现矛盾,输出NO
return 0;
}
}
}
cout << "Yes" << endl;//全部染色完成,没有矛盾,输出YES
return 0;
}
每次看海绵哥的原理都很省事,省的我去搜orz
海绵哥yyds
Or2
大佬们,为什么main函数里一定要遍历所有的点呢?所有连通块应该都是连通的吧
“for(int i = 1; i <= n; i++)
{
if(!color[i])
{
if(!dfs(i, 1))
{
cout << “No” << endl;
return 0;
}
}
}”
把这一段代码换成下面这段代码就不能行了,
“if(!dfs(1,1)) cout<<”No”<<endl;
else cout<<”Yes”<<endl;”
如果有三个点另外成环,整个环是一个孤立环,其他都满足二分图,但是这个孤立不满足二分图,二分图的点不一定连通
对
感谢感谢
我的嘴替
or2
这就是海绵哥
请问
if(!dfs(b, 3 - c)) return false
这一句,如果没染色不就递归把相邻点染了吗,那为啥还要返回false,而不是true成功染色?
染色不成功,说明存在奇数环,直接返回false
可以理解从b点开始去染色,是完成不行的,那么return false。那么起点u开始就染色不成功。
清晰易懂
想问一下佬们为什么int型常量为什么要设成100010 * 2呢,我设成100010就不能ac
无向图需要建立两条边 所以要开2倍空间
感谢感谢!
如何改变题解中图片大小,求大佬给下方法
哇塞真的很清晰!!懂啦!!%%%%
orz
有个问题为什么啊每次都将 该点染成1号色 但是之前不是已经染过其他色了吗
就是图中的每一个相互孤立的部分都是从1号颜色(下面把1号色叫做红色,2号色叫做黑色)开始染。
假设有1 <-> 3 <->2 <->6 <->1 , 4 <-> 9 <-> 8 <-> 5 <->4 的无向图
单个孤立的部分比如1 <-> 3 <->2 <->6 <->1 这个部分是从1号开始染色并染成红色,把3号,2号,6号染完之后,主函数中的for(int i = 1; i <= n; i++)//遍历点
{
if(!color[i])//如果没染色
{
if(!dfs(i, 1))//染色该点,并递归处理和它相邻的点…
}
会将4号点认作又一个起点染成又一个红色,继续染9号,5号,8号。
其实你可以把每个起点染成2号颜色,没有影响的
多谢多谢已经懂了哈哈感谢🙏🏻
确实
感谢
论题解,还得是海绵宝宝哥
大佬问一下 如果存在自环的话 那不就是自己和自己相邻吗?也就是存在自环的不是二分图是吧
是的
自环也可以看成奇数环,边数是1,也是奇数
tql海绵宝宝
orz
为什么不能在搜索时直接给颜色赋值,却要写在函数的调用处来进行颜色赋值啊
bool dfs(int u, int c)改成color[b] != 3 - c和bool dfs(int u)可以吧
这个题目应该出什么
你猜猜出什么
海绵哥题解真的清晰直观
请问为什么很多题不用头文件
#include <algorithm>
也能ac,为什么很多题解里都还是会带上这个头文件呢?良好习惯(狗头)
常用头文件,避免用的时候,忘加头文件然后ce了
你题解写的真好。
orz