二分图的重要性质:①一定不包含奇数环 ②可能不是连通图
通过染色法判断,环中节点交替被染两种颜色,若产生矛盾,则不是连通图
解题思路
color[i] = {0, 1, 2}
,i
可以被染成两种颜色,1
色或2
色,0
表示未被染色。
- 外层循环
1 ~ n
,由于原图可能不是连通图,所以需要将每个点当作起点做一遍dfs。 - 若
color[i] = 0
,即未被染色,进行dfs;若已染色不重复运行程序。 dfs(u, i)
过程:以u
为端点遍历所有邻接边。若另一个端点j
未被染色,对其进行染色并再次判断dfs(u, 3 - i)
;若另一个端点j
已染色,则继续判断color[j] == c
,若与端点u
相同,则说明产生冲突,返回false
。- 只能染
1
或2
,3 - i
必然是另一种颜色 - 程序正常运行到结束,返回
true
。
C++代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 100010, M = 200010;
int n, m;
int h[N], e[M], ne[M], idx;
int color[N];
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx;
idx++;
}
bool dfs(int u, int c)
{
color[u] = c;
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!color[j])
{
if (!dfs(j, 3 - c))
{
return false;
}
}
else
{
if (color[j] == c)
{
return false;
}
}
}
return true;
}
int main()
{
cin.tie(0);
ios::sync_with_stdio(false);
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;
}