闲的无聊来写个二分图的讲解吧。
读者可能会疑惑,二分图?什么叫做二分图,是由二分思想演变的图吗?
但是,二分图各位都见过,只是不知道它叫二分图。以下开始二分图的讲解
二分图:
大家小学肯定做过单词连线吧?(oh,小时候最让我头疼的东西了.. .0_._0.)
(原谅本蒟蒻英语不好...其实也不想写watermelon。。。)
没错!这就是二分图的原型!为什么说这是二分图的原型呢?大家请看二分图的定义就知道了。
二分图定义:
二分图又称作二部图,是图论中的一种特殊模型。设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G是一个二分图。
这定义没人讲解,萌新看了谁不迷糊啊?
咳咳,换句人话说就是:我们把上面图中,单词部分记为A部分,翻译部分记为B部分。我们可以知道,A和B部分的各个点(单词)没有相互连接的情况,A部分中的点是连向B部分中的点,再次解释一下这句话的意思,A中的某一个点,可以连向B中任意多个点,但是A,B各个部分中的点是没有相互连接的。于是,我们就可以得到一个常规的二分图:
到这里呢,我相信各位读者都以及明白了二分图是什么了,但是还有一个问题:如何判断一个图是二分图?
这里介绍一种常规的思想:染色法
我们选取A或者B部分中任意一个点进行染色:这里我们从A1开始进行染色
说明:因为二分图中,点与点的连线是没有方向的,如果一个图是二分图,那么这个图的每个点都是可以通过边到达的。也就是说,这里可以用DFS来进行染色。
我们把A部分的所有点染为数字1,B部分的所有点染为数字2。如果最后A中所有点都染为了1,B中所有点都染为了2,那么就说明该图是二分图啦!
废话不多说,直接上代码:
例题链接:http://oj.daimayuan.top/course/14/problem/797
#include<bits/stdc++.h>
using namespace std;
const int N = 1001;
vector<int>e[N];//用于存图
int n, m, c[N];//c数组用于染色
bool dfs(int x) {
for (auto y : e[x])
if (!c[y]) {
c[y] = 3 - c[x];
if (!dfs(y))
return false;
}
else if (c[x] == c[y])
return false;
return true;
}
bool check() {
memset(c, 0, sizeof(c));
for (int i = 1; i <= n; i++)
if (!c[i]) {
c[i] = 1;
if (!dfs(i)) {
return false;
}
}
return true;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
e[x].push_back(y);
e[y].push_back(x);
}
if (check()) printf("Yes\n");
else printf("No\n");
}