AcWing 860. 染色法判定二分图
题目描述
给定一个n个点m条边的无向图,图中可能存在重边和自环。
请你判断这个图是否是二分图。
输入格式
第一行包含两个整数n和m。
接下来m行,每行包含两个整数u和v,表示点u和点v之间存在一条边。
输出格式
如果给定图是二分图,则输出“Yes”,否则输出“No”。
数据范围
1 ≤ n,m ≤ 10^5,
1 ≤ m ≤ 2*10^5,
输入样式:
4 4
1 3
1 4
2 3
2 4
输出样式:
Yes
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, m = 100010;
int n; // n表示点数
int h[N], e[M], ne[M], idx; // 邻接表存储图
int color[N]; // 表示每个点的颜色,-1表示未染色,0表示白色,1表示黑色
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
// u表示当前节点,c表示当前点的颜色
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] == -1) // 如果j未染色
{
if (!dfs(j, !c)) return false; // 给j的相邻点染色
}
else if (color[j] == c) return false; // 如果邻边颜色和当前边颜色相同,则出错——————不是二分图
}
return true;
}
bool check()
{
memset(color, -1, sizeof color);
bool flag = true;
for (int i = 1; i <= n; i ++ ) // 给n个点的所有相邻点都尝试染色
if (color[i] == -1) // 如果i未染色
if (!dfs(i, 0)) // 如果在这个期间出错了
{
flag = false;
break;
}
return flag;
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, 0, sizeof h);
while(m -- )
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b), add(b, a);
}
bool res = check();
if(res) puts("Yes");
else puts("No");
return 0;
}