给定一个n个点m条边的无向图,图中可能存在重边和自环。
请你判断这个图是否是二分图。
输入格式
第一行包含两个整数n和m。
接下来m行,每行包含两个整数u和v,表示点u和点v之间存在一条边。
输出格式
如果给定图是二分图,则输出“Yes”,否则输出“No”。
数据范围
1≤n,m≤1051≤n,m≤105
输入样例:
4 4
1 3
1 4
2 3
2 4
输出样例:
Yes
染色思路
二分图:判断一个图是否二分图主要看这个图有没有奇数环,有奇数环的就不是二分图。
①:给定任意一个点开始染色,假设第一个点染色1,那么这个点的所有连通点都染色2,相对应的,染色2的点的所有连通点都染色为1
②:如果这个图所有点都染色后不会发生矛盾,那么该图就是二分图,否则就不是。
如图所示,这个图染色结束后并无冲突 所以是二分图:
这个图染色以后发生冲突 不是二分图:
代码详情如下
#include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N = 100010, M = 200010; //无向边所以M要*2 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 ++; } bool dfs(int u, int c) //u是当前节点,c是染色点 { color[u] = c; //首先给当前节点染c for(int i = h[u]; i != -1; i = ne[i]) //从前到后遍历节点 { int j = e[i]; //用j存储当前节点号数 if(!color[j]) //如果当前节点没有染色 { //把当前节点所连通的点都深搜, //然后染上3-c(如果当前是1,连通点应该染3-1=2;如果是2,连通点染3-2=1) if(!dfs(j, 3 - c)) return false; } //如果当前节点染色了并且和c相同,说明有奇数环 else if (color[j] == c) return false; } return true; } int main() { scanf("%d%d", &n,&m); memset(h, -1, sizeof h); while(m -- ) { int a,b; scanf("%d%d", &a, &b); add(a,b),add(b,a); } bool flag = true; //定义一个flag来判断当前图是否有矛盾 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; }