接下来的内容,是关于基础图论的最后一节:二分图的相关问题;
我们先简单介绍一下二分图,二分图不一定是一个连通块,可能是多个连通块组成,然后我们把所有的点分别划分为两个部分,一个在左边的点集中,另一个在右边的点集中,所有的边只存在于两个点集之间,而在点集内部是不会存在连边的,这样的图我们就叫作二分图;
这里我们要先介绍一下如何判定一个图是不是二分图,我们是通过染色法来确定的,我们给一个未染色的点染上白色,记为1,然后因为连边存在于点集之间,我们给与这个点相连的点都放在另一边并染成黑色,记为2,所以我们知道如果一个连通块中的一个点已经被染色,我们就可以去把所有的点都给染色,所以遍历一个连通块,我们在这里使用dfs的思路,染色法什么时候可以判断出这不是个二分图呢,就是我在遍历当前点的下一个点的时候发现下一个点已经被染色且与当前点的颜色一致,说明边出现在了点集内部,这不是一个二分图!
代码:
#include<bits/stdc++.h>
#define maxn 100010
#define maxm 200010
using namespace std;
int h[maxn],e[maxm],ne[maxm],idx;
int n,m;
int color[maxn];
void add(int a,int b){
e[idx] = b; ne[idx] = h[a] ; h[a] = idx++;
}
bool dfs(int t,int c){
color[t] = c;
for(int i = h[t];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()
{
memset(h, -1, sizeof h);
cin >> n >> m;
while (m -- ){
int a,b;
cin >> a >> b;
add(a, b); add(b, a);
}
bool flag = false;
for(int i = 1;i<=n;i++){
if(!color[i]){
if(!dfs(i , 1)) flag = true;
}
}
if(flag) cout << "No" << '\n';
else cout << "Yes" << '\n';
return 0;
}
分析:这里给dfs返回类型确定为bool类型已经不是第一次了,我们在拓扑排序的时候判断有没有环的时候就已经用到过了;
·这里利用3-c在1,2之间切换有点意思!