二分图(1)
二分图(1)
1.例题:染色法判断二分图
题目描述
给定一个 n 个点 m 条边的无向图,图中可能存在重边和自环。
请你判断这个图是否是二分图。
输入格式
第一行包含两个整数 \(n\) 和 \(m\)。
接下来 m 行,每行包含两个整数 \(u\) 和 \(v\),表示点 \(u\) 和点 \(v\) 之间存在一条边。
输出格式
如果给定图是二分图,则输出 Yes
,否则输出 No
。
数据范围
\(1≤n,m≤10^5\)
输入样例:
4 4
1 3
1 4
2 3
2 4
输出样例:
Yes
注:本题来源于AcWing第860题
2.思路
我们判断的是二分图,这时候我们就可以用染色法。
我们可以从任意一点开始染色,然后把这个点连通的所有点全都染成一样的颜色(用dfs进行)。
如果在染色的时候有冲突,就标记一下。
最后判断,如果没有标记就是二分图,有则不是。
3.代码
#include<iostream>
#include<cstring>
using namespace std;
const int N=100005;
int n,m;
int h[N],e[2*N],ne[2*N],idx;//存边的两个数组要开两倍,因为是无向边
int color[N];//染色数组
void add(int a,int b){//邻接表加边操作(加了两次)
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
e[idx]=a;
ne[idx]=h[b];
h[b]=idx++;
}
bool dfs(int u,int c){
color[u]=c;//先染色
for(int i=h[u];i!=-1;i=ne[i]){//遍历u所有能到达的边
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>>n>>m;
memset(h,-1,sizeof(h));
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
add(a,b);
}
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;
}
完~
又双叒叕水博客
如果觉得还不错的话,就点个赞吧,您的支持就是我最大的动力。