图论基础——二分图
Posted KaaaterinaX
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论基础——二分图相关的知识,希望对你有一定的参考价值。
二分图可以把图中所有顶点分到两个集合内,并且使得集合内部没有边。
重要性质:
一个图是二分图,当且仅当图中不含奇数环。
一、染色法判二分图
复杂度
O
(
n
+
m
)
O(n+m)
O(n+m)
运用深度优先搜索对节点逐个染色,遇到矛盾返回false,据此判断是否为二分图。
const int maxn=1e5+7;
vector<int> mp[maxn];
int c[maxn];//记录点的颜色
bool dfs(int u,int co){
c[u]=co;
for(int i=0;i<mp[u].size();i++){
int to=mp[u][i];
if(!c[to]){
if(!dfs(to,3-co)) return false;
}
else if(c[to]==co) return false;
}
return true;
}
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
mp[a].pb(b);
mp[b].pb(a);
}
int flag=1;
for(int i=1;i<=n;i++){
if(!c[i]){
//还没有染色
if(!dfs(i,1)){
flag=0;
break;
}
}
}
if(flag){
cout<<"Yes"<<endl;
}
else{
cout<<"No"<<endl;
}
}
二、匈牙利算法
最坏复杂度
O
(
n
m
)
O(nm)
O(nm),但是实际远小于此。
给定一个二分图,求最大匹配
P3386 【模板】二分图最大匹配
const int maxn=510;
vector<int> mp[maxn];
int match[maxn];
bool vis[maxn];
bool find(int u){
for(int i=0;i<mp[u].size();i++){
int to=mp[u][i];
if(!vis[to]){
vis[to]=1;
if(match[to]==0||find(match[to])){
match[to]=u;
return true;
}
}
}
return false;
}
int main(){
int n,m,e;
cin>>n>>m>>e;
for(int i=1;i<=e;i++){
int a,b;
cin>>a>>b;
mp[a].pb(b);//只需记录左边的节点指向右边的节点单向边
}
//枚举左边的点
int res=0;
for(int i=1;i<=n;i++){
memset(vis,0,sizeof vis);
if(find(i)) res++;
}
cout<<res<<endl;
}
图论题目难在抽象建图以及对模版的修改,重点还是多刷题,这篇博客记录基础模版,之后出刷题记录。
以上是关于图论基础——二分图的主要内容,如果未能解决你的问题,请参考以下文章