染色法判断二分图(加深对于DFS的理解于运用)
作者:互联网
染色法判定二分图
题目描述:
给定一个n个点m条边的无向图,图中可能存在重边和自环。
请你判断这个图是否是二分图。
输入格式
第一行包含两个整数n和m。
接下来m行,每行包含两个整数u和v,表示点u和点v之间存在一条边。
输出格式
如果给定图是二分图,则输出“Yes”,否则输出“No”。
数据范围
1≤n,m≤105
输入样例:
4 4
1 3
1 4
2 3
2 4
输出样例:
Yes
这个题目的话主要就是对于DFS的运用和理解了,我作为一个初学者,是这么理解的,如果你单纯的以一个递归的角度去思考DFS的话,你会发现很难思考,因为它很复杂,循环中的递归。但是如果你以另外一种逻辑思维去思考的话,那么它就会变得通俗易懂。
比如这个题目,我们遍历图中的每一个点,如果这个点没有染色,那么我们将它染色,再通过这个点,寻找一下与它相邻的点,如果相邻的点没有染色,那就将其染色,如果寻找的过程中发现与其相邻的点中有颜色和其一样的点,那么发现错误,返回false,以此类推,就可以了。
有了上述的一个总体的逻辑思维,我们再通过这个逻辑思维去构造这个递归,就可以了。其实我们不需要知道具体的递归如何执行(当然了知道更好),我们只需要知道我们构造的递归符合我们的逻辑思维和我们的意愿即可,所以这对于刚刚入门的我帮助还是比较大的,这是一种全新的思维方式,即:对于某一种操作,我们并不需要知道其每一步的详细具体操作,我们只需要知道它的逻辑性以及正确性即可,具体的操作步骤可能会很复杂很复杂,但是只要它符合我们的逻辑以及正确就可以了。
所以我们在构造DFS的时候,要从逻辑思维的角度出发,而不是去死磕每一步应该如何做。
所以这篇文章的意义就在于提升我的理解与运用DFS的能力,获得一种全新的思维方式!!!
下面是AC代码+注释:
#include <iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 200010;
int h[N], e[N], ne[N], idx = 0;
int color[N];
int n, m;
void connect(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
bool dfs(int x, int c)
{
color[x] = c;//染色
for (int i = h[x]; i != -1; i = ne[i])//遍历一下它所连接的所有点
{
if (!color[e[i]])//如果这个点没有被染色
{
if (!dfs(e[i], 3 - c))//那我们就把他染成另外一种颜色,如果过程中有错误,那么返回false;
return false;
}
if (color[e[i]] == color[x])//如果相邻的两边颜色相等,那么就有问题,返回错误
return false;
}
return true;//如果没有问题,返回true;
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while (m--)
{
int a, b;
scanf("%d%d", &a, &b);
connect(a, b);
connect(b, a);
}
bool flag = 1;//用于判断过程中是否出错
for (int i = 1; i <= n; i++)//遍历一下所有的点,判断
{
if (!color[i])//如果这个点没有染色
{
if (!dfs(i, 1))//那么就把这个点染成1号色,如果过程中出现错误
{
flag = 0;
break;
}
}
}
if (flag)printf("Yes");
else printf("No");
return 0;
}
碰到一些重要的而且好的知识点或者是思维方式,一定要及时记录下来以便复习的时候利用。
好了,每篇博客后面都附上一句话。
你没有回我信息,我也再也没有给你发信息,但是我知道我们并没有结束。
标签:二分,递归,逻辑思维,int,染色,DFS,color,染色法 来源: https://blog.csdn.net/weixin_52985599/article/details/113833105