当前位置:网站首页>神机百炼3.54-染色法判定二分图
神机百炼3.54-染色法判定二分图
2022-07-02 05:55:00 【starnight531】
染色法
食用指南:
对该算法程序编写以及踩坑点很熟悉的同学可以直接跳转到代码模板查看完整代码
只有基础算法的题目会有关于该算法的原理,实现步骤,代码注意点,代码模板,代码误区的讲解
非基础算法的题目侧重题目分析,代码实现,以及必要的代码理解误区
题目描述:
给定一个二分图,其中左半部包含 n1 个点(编号 1∼n1),右半部包含 n2 个点(编号 1∼n2),二分图共包含 m 条边。
数据保证任意一条边的两个端点都不可能在同一部分中。
请你求出二分图的最大匹配数。二分图的匹配:给定一个二分图 G,在 G 的一个子图 M 中,M 的边集 {E} 中的任意两条边都不依附于同一个顶点,则称 M 是一个匹配。
二分图的最大匹配:所有匹配中包含边数最多的一组匹配被称为二分图的最大匹配,其边数即为最大匹配数。输入格式
第一行包含三个整数 n1、 n2 和 m。
接下来 m 行,每行包含两个整数 u 和 v,表示左半部点集中的点 u 和右半部点集中的点 v 之间存在一条边。输出格式
输出一个整数,表示二分图的最大匹配数。数据范围
1≤n1,n2≤500,
1≤u≤n1,
1≤v≤n2,
1≤m≤105
输入样例:
2 2 4
1 1
1 2
2 1
2 2
输出样例:
2题目来源:https://www.acwing.com/problem/content/863/
题目分析:
- 染色法经典题目:针对每点,若将其染为x色,则将其邻接点染为另一色。
最终图中每一点都成功着色,则该图为二分图。
反之若某点出现染色矛盾,既应该染x色,又应该染另一色,则该图不为二分图。 - 染色法分为两种:dfs实现 & bfs实现
下面来讲同为O(n)的两种染色法判定二分图
算法原理:
模板算法:
染色法:
1. 二分图:
- 定义:
对于每一条边,将其两个端点放置在不同的两个集合中。
若最终图中所有点完美被划分到两个不同集合中,则该图为二分图。 - 性质:
可以用两种颜色无冲突的着色图中所有点。 - 举例:
二分图:
非二分图:
2. 两大步骤:
对于每一个点,不论dfs还是bfs,任务有二:
为当前未着色点着色 & 查看邻接点和当前点是否存在冲突。
为当前未着色的x点染色y:
遍历当前x点的邻接点,逐个判断是否与当前点冲突:
若邻接点已经着色,且为y,则出现着色冲突,直接判定非二分图。
若邻接点已经着色,且为y的对立色,则继续为下一个邻接点着色。
若邻接点未着色,则将其染色为y的对立色,之后继续为下一个邻接点着色。
代码实现:
dfs实现染色法
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200020; //m条边,则2m个点
int color[N]; //标记每个点的颜色,二分图只需1 & 2两种颜色
int h[N], val[N], ne[N];
int idx;
void add(int x, int y){
val[idx] = y;
ne[idx] = h[x];
h[x] = idx++;
}
int n,m;
bool dfs(int x, int y){
color[x] = y;
for(int i = h[x]; i!=-1; i=ne[i]){
if(color[val[i]] == y){
//检查已着色点是否含有着色冲突
return false;
}else if(!color[val[i]]){
//为未着色点着色
if(!dfs(val[i],3-y))
return false;
}
}
return true;
}
int main(){
memset(h, -1, sizeof(h));
cin >>n >>m;
int a = 0, b = 0;
while(m--){
cin >>a >>b;
add(a, b);
add(b, a);
}
//可能是非连通图,每个连通分量都需要染色
for(int i=1; i<=n; i++){
if(!color[i]){
if (!dfs(i,1)){
cout << "No"<<endl;
return 0;
}
}
}
cout <<"Yes"<<endl;
return 0;
}
bfs实现染色法:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 200020;
int h[N], val[N], ne[N];
int idx;
void add(int x, int y){
val[idx] = y;
ne[idx] = h[x];
h[x] = idx++;
}
int n, m;
int color[N];
int tt = 0, hh = 0;
int que[N];
bool bfs(int x, int y){
que[tt++] = x; //从que[0]开始存储
color[x] = y;
while(hh < tt){
//开始hh==tt==0时,队列为空;所以只有hh<tt时队列中含有元素
int t = que[hh++];
for(int i=h[t]; i!=-1; i=ne[i]){
if (color[val[i]] == color[t]){
//检查已着色相邻点是否存在颜色冲突
return 0;
}else if (!color[val[i]]){
//为未着色的点着色
color[val[i]] = 3-color[t];
que[tt++] = val[i];
}
}
}
return 1;
}
int main(){
memset(h, -1, sizeof h);
cin >>n >>m;
int a=0, b=0;
while(m--){
cin >>a >>b;
add(a, b);
add(b, a);
}
//非连通图的每个连通分量都需要染色
for(int i=1; i<=n; i++){
if (!color[i]){
if (!bfs(i, 1)){
cout<< "No";
return 0;
}
}
}
cout<< "Yes";
return 0;
}
代码误区:
1. 两种颜色的转换技巧:
- 假设两种颜色为x色和y色,且记x+y的和为s
这一点染色为x,则下一点染色为s-x
2. 易漏点:非连通图
- 当已经对全图中一点进行染色法,但是仍存在某些点未被着色,说明图是非连通图。
- 对于非连通图的每一个连通分量,选择其中一点进行染色法。
- 每进行一次染色法,都要继续遍历所有点,检查是否还存在未被染色的连通分量。
3. DFS和BFS的相同点:
- 都是在给未染色的点着色时,发现这一点与已染色的相邻点发生了冲突。
本篇感想:
染色法本身理解和实现都较为简单,只需记住两点:
给未染色的点染色 & 检查当前点是否和已染色的相邻点发生染色冲突。
看完本篇博客,恭喜已登 《筑基境-后期》
距离登仙境不远了,加油
边栏推荐
- Alibaba: open source and self-developed liquid cooling data center technology
- cookie插件和localForage离线储存插件
- 脑与认知神经科学Matlab Psytoolbox认知科学实验设计——实验设计四
- 【論文翻譯】GCNet: Non-local Networks Meet Squeeze-Excitation Networks and Beyond
- 测试 - 用例篇
- Technologists talk about open source: This is not just using love to generate electricity
- Thread pool overview
- LCD之MIPI协议的一些说明
- STC8H8K系列匯編和C51實戰——數碼管顯示ADC、按鍵串口回複按鍵號與ADC數值
- How to write good code - Defensive Programming Guide
猜你喜欢
3D printer G code command: complete list and tutorial
Oled12864 LCD screen
软件测试答疑篇
RGB 无限立方体(高级版)
Can't the dist packaged by vite be opened directly in the browser
OLED12864 液晶屏
How to write good code - Defensive Programming Guide
Eco express micro engine system has supported one click deployment to cloud hosting
Regular expression summary
Grbl software: basic knowledge of simple explanation
随机推荐
Zzuli:1065 count the number of numeric characters
数理统计与机器学习
3D printer G code command: complete list and tutorial
Uva548 tree
【LeetCode】Day92-盛最多水的容器
2022-2-15 learning xiangniuke project - Section 8 check login status
PHP read file (read JSON file, convert to array)
php按照指定字符,获取字符串中的部分值,并重组剩余字符串为新的数组
【论文翻译】GCNet: Non-local Networks Meet Squeeze-Excitation Networks and Beyond
Generics and generic constraints of typescript
Common protocols and download paths of NR
Addchild() and addattribute() functions in PHP
PHP obtains some values in the string according to the specified characters, and reorganizes the remaining strings into a new array
[Chongqing Guangdong education] selected reading reference materials of British and American literature of Nanyang Normal University
文件包含漏洞(一)
Several keywords in C language
Balsamiq wireframes free installation
STC8H8K系列汇编和C51实战——串口发送菜单界面选择不同功能
TypeScript的泛型和泛型约束
数据库学习总结5