如果一张无向图的N个结点可以分成A,B两个非空集合,其中 A ∩ B = ∅ A\cap B=\emptyset A∩B=∅,并且在同一集合内的点之间都没有边相连,则称这张图为二分图。

二分图判定

定理:一张图是二分图,当且仅当图中不存在奇环(长度为奇数的环)。

P1330 封锁阳光大学

染色法判定:尝试用黑白两色标记,当一个结点被标记后,它的所有相邻结点应该被标记与之相反的颜色,若该标记过程中出现冲突,则说明图中存在奇环。

下用BFS、DFS、并查集分别实现。

BFS

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10,M=2e5+10;
int head[N],ver[M],nex[M],vis[N];
int n,m,u,v,tot=0,ok=1;
int sum[5],ans;void add(int u,int v)
{ver[++tot]=v;nex[tot]=head[u];head[u]=tot;
}bool bfs(int start,int color)
{queue<int>q;q.push(start);vis[start]=color;//printf("vis[%d]=%d\n",start,vis[start]);sum[1]=1,sum[2]=0;//初始化while(q.size()){int now=q.front();q.pop();for(int i=head[now];i;i=nex[i]){int to=ver[i];if(vis[to]==0) {if(vis[now]==1) vis[to]=2,sum[2]++;else vis[to]=1,sum[1]++;//printf("vis[%d]=%d\n",to,vis[to]);q.push(to);}else if(vis[to]==vis[now]) return false;}}return true;
}int main()
{cin>>n>>m;for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);add(u,v),add(v,u);}for(int i=1;i<=n;i++){if(vis[i]) continue;//vis[i]==0的话表明跟之前的结点都不连通 if(!bfs(i,1)){ok=0;break;}else ans+=min(sum[1],sum[2]);//加和}if(ok) cout<<ans<<endl;else cout<<"Impossible"<<endl;return 0;
}

DFS

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10,M=2e5+10;
int head[N],ver[M],nex[M],vis[N];
int n,m,u,v,tot=0,ok=1;
int sum[5],ans;void add(int u,int v)
{ver[++tot]=v;nex[tot]=head[u];head[u]=tot;
}bool dfs(int now,int color)
{for(int i=head[now];i;i=nex[i]){int to=ver[i];if(!vis[to]) {if(vis[now]==1) vis[to]=2,sum[2]++;else vis[to]=1,sum[1]++;dfs(to,vis[to]);}else if(vis[to]==vis[now]) return false;}return true;
}int main()
{cin>>n>>m;for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);add(u,v),add(v,u);}for(int i=1;i<=n;i++){if(vis[i]) continue;//vis[i]==0的话表明跟之前的结点都不连通 sum[1]=1,sum[2]=0;vis[i]=1;if(!dfs(i,1)){ok=0;break;}else ans+=min(sum[1],sum[2]);//加和}if(ok) cout<<ans<<endl;else cout<<"Impossible"<<endl;return 0;
}

并查集二分图的判定(“扩展域”的并查集):

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10,M=2e5+10;
int f[N*2],size[N];
int n,m,x,y,tot=0,ok=1;int find(int x)
{if(f[x]==x) return f[x];else return f[x]=find(f[x]);
}int main()
{cin>>n>>m;for(int i=1;i<=2*n;i++)f[i]=i;for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);int fx1=find(x),fy1=find(y);int fx2=find(x+n),fy2=find(y+n);if(fx1==fy1){ok=0;break;}else f[fx2]=fy1,f[fy2]=fx1;}if(ok) cout<<"OK"<<endl;else cout<<"Impossible"<<endl;return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10,M=2e5+10;
int f[N*2],size[N*2],mem[N*2],h[N];
//1~n白染色域,n+1~2n黑染色域
int n,m,x,y,tot=0,ok=1,ans;int find(int x)
{if(f[x]==x) return f[x];else return f[x]=find(f[x]);
}
void merge(int x,int y)
{int fx=find(x);if(fx!=y){f[y]=fx;size[fx]+=size[y];}
}
int main()
{cin>>n>>m;for(int i=1;i<=n;i++)f[i]=i,size[i]=1;for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);//每条边的两个顶点必不在一个染色域 int fx=find(x),fy=find(y);if(fx==fy)//在同一个染色域 {cout<<"Impossible"<<endl;return 0;}else{if(h[x]) merge(h[x],fy);if(h[y]) merge(h[y],fx);h[x]=fy,h[y]=fx;}}for(int i=1;i<=n;i++){int q=find(i);if(!mem[q])//一个未处理过的并查集 {int p=find(h[i]);mem[p]=mem[q]=1;ans+=min(size[p],size[q]);//两域取其小 }}cout<<ans<<endl;return 0;
}

二分图最大匹配

匈牙利算法(增广路算法):

P3386 【模板】二分图最大匹配

尝试给每个左部结点x匹配一个右部结点y。y能与x匹配的条件:

  1. y本身就是非匹配点;
  2. y已经与x’匹配,但从x’出发能找到另一个y’与x’匹配。

特点:当一个结点成为匹配点之后,至多因为找到增广路而更换匹配对象,但是不会变回非匹配点。

#include<bits/stdc++.h>
using namespace std;
const int N=520;
int n,m,e,tot,ans;
int mp[N][N],vis[N],match[N];bool dfs(int x)
{for(int i=1;i<=m;i++){if(!mp[x][i]||vis[i]) continue;vis[i]=1;if(!match[i]||dfs(match[i])){match[i]=x;return true;}}return false;
}int main()
{cin>>n>>m>>e;for(int i=1;i<=e;i++){int x,y;scanf("%d%d",&x,&y);mp[x][y]=1;}for(int i=1;i<=n;i++){memset(vis,0,sizeof(vis));if(dfs(i)) ans++;}cout<<ans;
}

二分图的判定最大匹配相关推荐

  1. 【算法】二分图的判定

    二分图的判定 给定一个具有n个顶点的图.要给图上每个顶点染色,并且要使相邻的顶点颜色不同. 判断是否能最多用两种颜色进行染色.题目保证没有重边和自环. 概念:把相邻顶点染成不同颜色的问题叫做图的着色问 ...

  2. 二分图的判定(模板)

    采用DFS和黑白二着色的方法判定二分图 vector<int> g[maxn];//邻接表 int color[maxn];//1,2分别代表黑色和白色,0表示还没着色,调用前要把colo ...

  3. Uva 10004(二分图的判定)

    这题其实很简单的说,第一次用邻接表来存图= = 首先图的储存结构是结构体+head数组...其实head数组保存的 struct node {int v;int next; }V[200*200]; ...

  4. 【二分图】【最大匹配】【匈牙利算法】CODEVS 2776 寻找代表元

    裸的匈牙利,存模板. 1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 using names ...

  5. 东哥带你刷图论第四期:二分图的判定

    学算法认准 labuladong 点击卡片可搜索关键词

  6. 过山车(二分图_求最大匹配数)

    Description RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了.可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner ...

  7. 【HDU - 2444】The Accomodation of Students(二分图判断 + 匈牙利算法求最大匹配)

    题干: There are a group of students. Some of them may know each other, while others don't. For example ...

  8. 二分图判断以及二分图最大匹配

    概念 二分图又称作二部图 ,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的 ...

  9. 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配

    二分图匹配 二分图大讲堂--彻底搞定最大匹配数(最小覆盖数).最大独立数.最小路径覆盖.带权最优匹配(转) 文本内容框架: §1图论点.边集和二分图的相关概念和性质 §2二分图最大匹配求解 匈牙利算法 ...

最新文章

  1. 全球首个 AI 说唱歌手 TikTok 发新歌,虚拟偶像正当时
  2. 在idea做项目时 在进行模糊查询的时候页面为什么拿不到值_深入浅出Performance工具解决Web页面性能问题
  3. [c]如何通过结构体元素找到结构体?
  4. 全球及中国管道运输行业建设发展与投资战略规划报告2022版
  5. linux ps转为tiff,转换为TIFF,将图像转换为TIFF,在线图像转换为TIFF
  6. 会签 数据库表设计_关于数据库表设计和实体类设计的思考
  7. docker php 乱码,如何解决docker安装zabbix5.0界面乱码
  8. Mybatis(14)多表查询
  9. Anaconda 国内镜像源整理
  10. iOS环境,Appium不支持driver.current_activity等操作
  11. mysql数据库函数详解_MySQL数据库之字符函数详解
  12. Nginx源码阅读 ---- 模块的初始化过程,工作进程中初始化事件模块
  13. 时域有限差分法matlab程序,时域有限差分法的Matlab仿真
  14. java docx4j_docx4j基本操作
  15. 《C语言运算符100例》优先级面试错题
  16. matlab牛头刨床矩阵,MATLAB牛头刨床分析程序-课程设计
  17. 深度优先搜索-迷宫问题
  18. OpenStack-Placement、nova组件部署
  19. 【Android】debug 状态下其签名文件 debug.keystore 相关(如何获得该文件,其密码,获取其sha1、MD5等)
  20. python语言是编译型语言-解释型语言与编译型语言

热门文章

  1. 【小概念】格拉姆矩阵(gram matrix)
  2. jQuery过滤器:筛选jquery对象数组中的DOM对象
  3. NProgress.js进度条
  4. 视频教程-游戏网络编程必备知识-Unity3D
  5. 直接添加集合对象Arrays.asList()
  6. TTSR:用Transformer来实现端到端的超分辨率任务 | CVPR2020
  7. msdn i tell you网址及下载系统详细步骤
  8. 使用 SysRq 查看系统信息
  9. linux基础 linux命令跟踪 strace命令
  10. 中缀转后缀并分别计算