二分图
「理论上到现在应该已经学习完了所有 NOIP 考纲内的知识点,如果还有不会的赶紧学习。」
突然发现自己从来没有学过二分图。
想起来去年本来想学,但是看了一下好像没怎么考,学别的去了。
二分图基础
定义
对于一张图,如果其点集可以划分为两个部分,且图上的每一条边的两个端点都不在同一个部分中,则称这个图为「二分图」。
形式化地,设图 \(G=(V,E)\),若 \(V=X\cup Y,X\cap Y=\varnothing\),则对于 \(\forall (u,v)\in E\) 有 \(u\in X,v\in Y\),则 \(G\) 为二分图。
常见的二分图有:树、偶环、网格。
如果已知 \(G=(V,E),V=X\cap Y,X\cap Y=\varnothing\),则二分图 \(G\) 也可记作 \(G=(X,Y,E)\)。
性质
- 二分图可以仅用两种颜色对所有节点染色,且没有边连接颜色相同的点。
- 二分图中不存在奇环。
- 二分图的各连通块互不影响。
性质 \(1\) 是显然的,且性质 \(1\) 与二分图的定义等价。
对于性质 \(2\),考虑奇环不满足性质 \(1\)。
判定
常用的判定方法有:
- 可以仅用两种颜色对所有节点染色,且没有边连接颜色相同的点的图为二分图。
- 不存在奇环的图为二分图。
判定方法 \(1\) 与定义等价。
对于判定方法 \(2\),考虑到原图要么是树,要么是含有偶环的图。前者是二分图,而后者也是,因为将偶环缩为一个点不影响其是否为二分图,则等价于一棵树。
实际应用中,就常常通过在图上染色的方式来判定二分图——间隔染色,如果当前节点 \(x\) 应该染的颜色 \(\textit{color}\) 与之前染的颜色 \(\textit{vis}_x\) 不同,则不为二分图。
虫子还有同性恋。给定 \(n\) 个点,\(m\) 条边,求能否将所有节点划分为两个部分,使得所有边连接的节点都处于不同部分,多测。如果可以,输出
No suspicious bugs found!,否则输出Suspicious bugs found!。
显然是二分图判定问题。注意要对所有连通块进行 DFS 判断。时间复杂度 \(\mathcal O(n+m)\)。
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=2000,M=1e6;
int n;
vector<int>g[N+1];
int vis[N+1];
void dfs(int x,int fx,int color,bool &ans){
if(vis[x]){
if(vis[x]!=color){
ans=true;
}
return;
}
vis[x]=color;
for(int i:g[x]){
if(i==fx){
continue;
}
dfs(i,x,color^3,ans);
if(ans){
return;
}
}
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
for(int i=1;i<=T;i++){
int m;
cin>>n>>m;
for(int i=1;i<=n;i++){
g[i].resize(0);
}
while(m--){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
bool ans=false;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
if(!vis[i]){
dfs(i,0,1,ans);
}
}
cout<<"Scenario #"<<i<<":\n";
if(ans){
cout<<"Suspicious bugs found!\n";
}else{
cout<<"No suspicious bugs found!\n";
}
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}
二分图应用
二分图性质简单,有诸多应用。
二分图最大匹配
图的匹配
无向图 $G=(V,E)$ 的匹配为边集 $M\subseteq E$,且 $M$ 中的边没有共顶点。
即从图中选择若干条没有共顶点的边。

浙公网安备 33010602011771号