AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
    • 吐槽
  • App
  • 登录/注册

AcWing 860. 染色法判定二分图---$\color{green}{详细代码注释+图解}$    原题链接    简单

作者: 作者的头像   Hasity ,  2022-03-28 23:39:02 ,  所有人可见 ,  阅读 3387


105


34

acwing 题解交流群:AcChat私聊我,拉你进群。

什么叫二分图

  • 有两顶点集且图中每条边的的两个顶点分别位于两个顶点集中,每个顶点集中没有边直接相连接!

  • 说人话的定义:图中点通过移动能分成左右两部分,左侧的点只和右侧的点相连,右侧的点只和左侧的点相连。

  • 下图就是个二分图:

二分图 -w150

  • 下图不是个二分图:

1.png


如果判断一个图是不是二分图?

  • 开始对任意一未染色的顶点染色。

  • 判断其相邻的顶点中,若未染色则将其染上和相邻顶点不同的颜色。

  • 若已经染色且颜色和相邻顶点的颜色相同则说明不是二分图,若颜色不同则继续判断。

  • 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;
}

31 评论


用户头像
霉菌素   7个月前      3    踩      回复

每次看海绵哥的原理都很省事,省的我去搜orz

用户头像
小飞棍来no   7个月前         踩      回复

海绵哥yyds


用户头像
WhiteAlbum2   1天前         踩      回复

请问
if(!dfs(b, 3 - c)) return false
这一句,如果没染色不就递归把相邻点染了吗,那为啥还要返回false,而不是true成功染色?


用户头像
半醒的狐狸   2个月前         踩      回复

海绵哥题解真的清晰直观


用户头像
Shier833_Ww   3个月前         踩      回复

请问为什么很多题不用头文件#include <algorithm>也能ac,为什么很多题解里都还是会带上这个头文件呢?

用户头像
学习爱我   2个月前         踩      回复

良好习惯(狗头)


用户头像
xiwang17   3个月前         踩      回复

你题解写的真好。


用户头像
Zh0uKal1   4个月前         踩      回复

orz


用户头像
ANDstephen   4个月前         踩      回复

大佬问一下 如果存在自环的话 那不就是自己和自己相邻吗?也就是存在自环的不是二分图是吧

用户头像
mol_cola   2个月前         踩      回复

是的

用户头像
snowstorm   2个月前         踩      回复

自环也可以看成奇数环,边数是1,也是奇数


用户头像
ZPLAYER   4个月前         踩      回复

什么情况是不可以将下一个点成功染色从而返回false呢

用户头像
颓废   3个月前      4    踩      回复

我的理解是if(!dfs(b, 3 - c)) return false;这句不是用来判断下个点不能成功染色而返回false,因为下一个点没染色的话一定能染成另一种颜色,这句话是用来判断是否矛盾的,就下面那个else if里的内容,如果矛盾会返回false,if(!dfs(b, 3 - c)) return false;if里是如果返回了false会一直返回false直到最外层也返回false,就会在main函数里判断出false。

用户头像
ZPLAYER   3个月前    回复了 颓废 的评论         踩      回复

感谢佬,已经懂了,orz

用户头像
秋与求醉   3个月前    回复了 颓废 的评论         踩      回复

英雄所见略同

用户头像
镜湖元   11天前    回复了 颓废 的评论         踩      回复

确实,只要后续有一个点不满足染色条件就一直返回false


用户头像
小桑要读研   7个月前         踩      回复

大哥 tql


用户头像
zz哲   8个月前         踩      回复

tql海绵宝宝


用户头像
彼岸花开_2   8个月前         踩      回复

include[HTML_REMOVED]

include[HTML_REMOVED]

using namespace std;

const int N=100010;

int n,m;
int h[N],ne[N],e[N],idx;
int color[N];//颜色

void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

bool dfs(int u,int r)//当前点 当前点要染的颜色
{
color[u]=r;

for(int i=h[u];i!=-1;i=ne[i])
{
    int j=e[i];

    if(!color[j])
    {
       if (!dfs(j,3-r)) 
        return false;
    }
    else if(color[j]==r) 
    return false;

}

return true;

}

int main()
{
memset(h,-1,sizeof(h));

cin>>n>>m;

while(m--)
{
    int a,b;

    cin>>a>>b;

    add(a,b);
    add(b,a);

}

bool flag=true;

for(int i=1;i<=n;i++)
{
    if(!color[i])
      if(!dfs(i,1))
      {
        flag=false;
        break;
      }
}

if(flag) cout<<"Yes";
else cout<<"No";

return 0;

}

用户头像
Hasity   8个月前         踩      回复

在idedubug下,容易找到原因。


用户头像
彼岸花开_2   8个月前         踩      回复

为什么我的深搜就超时了


用户头像
yydsw2x   9个月前         踩      回复

tql


用户头像
夏日晴空.   9个月前         踩      回复

爱了爱了


用户头像
xyh2   9个月前         踩      回复

这个太强了,真的喜欢


用户头像
新人orz   9个月前         踩      回复

https://blog.csdn.net/WJPnb1/article/details/126332263?spm=1001.2014.3001.5501 第一次写csdn博客,写了这个找二分图最大匹配的,大家可以来看看,有问题交流交流

用户头像
Hasity   9个月前         踩      回复

赞

用户头像
新人orz   9个月前    回复了 Hasity 的评论         踩      回复

😘


用户头像
zhangjh024   2022-04-02 10:13         踩      回复

复习起来很有用,感谢整理


用户头像
Rain丶bow   2022-03-30 21:05         踩      回复

代码更好理解,hh,加油


用户头像
Rain丶bow   2022-03-30 21:02         踩      回复

建议图给的简单易懂,这样太耗眼了,hh


用户头像
Hasity   2022-03-28 23:54         踩      回复

如何改变题解中图片大小,求大佬给下方法


你确定删除吗?

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息