二分图白话定义:能将一张图上的点分入两个集合,且集合内不存在边,边只存在于两个集合之间,那么这样的图就是二分图
思路:首先因为要判断图是否是二分图,那么可以借助染两种色把图的点分为两个集合,以黑白两色为例,先定义任意一点为白色,那么它的邻接点就都涂成黑色,如果整个图上色结束都没有出现冲突(相邻两点同色)那么这就是一个二分图,反之则图上存在奇数环,不能构成二分图(奇数环为节点是奇数的环,走完一圈会发现起点处的颜色是不一样的)
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10,M = 2 * N;
int n,m;
int h[N],ne[M],e[M],idx;
int color[N];
void add(int a,int b)// 见笔记 846
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
bool dfs(int u,int v)
{
color[u] = v;//假设1为白色,2为黑色
for(int i = h[u];i != -1;i = ne[i])//找u点的相邻点
{
int j = e[i];
if(!color[j])//没染过色
{
if(!dfs(j,3 - v)) //染成与当前点不同的颜色
return false;
}
else if(color[j] == v) //相邻点染过色但是和当前点颜色一致,有错误
return false;
}
return true;
}
int main()
{
cin >> n >> m;
memset(h,-1,sizeof h);//同 846
while(m--)
{
int a,b;
scanf("%d%d",&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) puts("Yes");
else puts("No");
return 0;
}