二分图定义

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

二分图的判定

给多组点,我们该如何判断能不能构成二分图呢?

至少有两个顶点且没有奇环的图才能构成二分图

判断二分图最常见的方法就是染色法,顾名思义,染色法就是使用黑白两种颜色对所有点都染上色,且相连的点点颜色不同,如果可以实现,则是二分图

可以用dfs和bfs去写,我这里给出bfs的代码

bool bfs(){queue<int>q;q.push(1);//将第一个点塞进去co[1] = 1;//染色颜色1while (!q.empty()){int u = q.front();q.pop();for(int i = 1; i <= n; ++i){if(tr[u][i]){//用的是邻接矩阵,所以判断u到i是否相连if(!co[i]){//如果没有染色co[i] = co[u] == 1 ? 2 : 1;//就染上和u不同的颜色q.push(i);//塞进队列}else if(co[i] == co[u])return false;//如果颜色和u相同,说明出现奇环,返回false即可}}}return true;
}

思考:

如果是一边加边,一边询问能否构成二分图

思路:

种类并查集

类似于上次那个食物链的题,1-n是假设A是在左边,n+1 - 2*n是假设A在右边,find(A)应该等于find(B+n),find(A + n)应该等于find(B), 每次给出新的边的时候,就判断一下,如果符合,就和类似于上面去emerge一下

二分图最大匹配

二分图最大匹配的定义

给定一个二分图G,在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,则称M是一个匹配。选择这样的边数最大的子集称为图的最大匹配问题(maximal matching problem)。

通俗点讲,就是海王们的配对

有一堆男海王,一堆女海王,各自都有倾慕的对象们,你是月老,负责牵线,在不考虑gay的情况下,要尽可能多的去给男海王与女海王来一一配对,这就是二分图的最大匹配

是不是及其生动形象

匈牙利算法(海王们的渣男渣女行为)

先引入题目背景:

有一场宴会,男孩和女孩组成舞伴,并且他们必须互相喜欢才能成为舞伴,一个男孩可能喜欢0个或多个女孩,一个女孩也可以喜欢0个或多个男孩,但一个男孩和他喜欢地女孩成为舞伴以后就不能和其他他喜欢的女孩成为舞伴,女孩亦是如此,问最多可以有多少对舞伴

算法思想:(划重点!!!

  • 对于一个男孩x,如果他喜欢对女孩y没有舞伴,那他们俩就成为了舞伴
  • 如果y已经有舞伴了,假设y的舞伴叫z。z看这情况心想:嘶,看架势我有可能被绿,这不行,我得先找好下家,我从来都是绿别人,哪有被反绿的,所以 z 就会去找他的其他喜欢的女孩,
    • 如果 z 发现自己可以找到新的喜欢的舞伴,那 z 就绿了 y ,然后y也绿了z, x 就顺理成章的和 y 在一起,这样最大匹配值就+1了
    • 如果 z 找不到新的舞伴,那这个时候 y 就觉得:啊,我们好歹情侣一场,有感情了,你找不到下家的话,我就不绿你了。
    • 这个时候 x 内心:小丑竟是我自己
  • z 去找下家的时候,其实又回到了 x 找舞伴的情况,也就是回到了起点,这就形成了递归其实

你以为是 z 绿了y,但一开始其实是 y 要绿了z,所以到底是谁先绿了谁,有待商榷(bushi

引申出来的人生哲理

  • 下手要趁早,因为越晚去邀请人家,配对成功的可能性就比较小,因为人家舞伴都满了,就不跟你一起(所以表白要趁早
  • 做人不要太渣,二分图匹配的过程就展示了一个绿人者终被绿的过程,你根本不知道你会在什么时候被什么人绿(手动狗头

代码实现

代码实现的过程包括两部分:dfs函数与一个for循环

bool dfs(int u){ //邻接矩阵建图的代码 for(int i = 1; i <= n; ++i){//对 u 这个点去循环他喜欢的人if(!vis[i] && tr[u][i]){//如果他喜欢的 i 没有出现在此次x找舞伴的过程中vis[i] = 1;if(!link[i] || dfs(link[i])){//如果 i 没有舞伴,或者 i 的舞伴可以绿他,就安排 i 和 u 在一起link[i] = u;return true;}}}return false;
}bool dfs(int u){ //链式前向星建图的代码for(int i = head[u]; i != -1; i = tr[i].next){int v = tr[i].to;if(!vis[v]){vis[v] = 1;if(link[v] == -1 || dfs(link[v])){link[v] = u;return true;}}}return false;
}
for(int i = 1; i <= n; ++i){//对每个人都去找舞伴mem(vis, 0);if(dfs(i))++ans;
}

时间复杂度

邻接矩阵建图法:O(n3)O(n^3)O(n3),n是点数

链式前向星建图法: O(n∗m)O(n*m)O(n∗m),m是总边数

König定理

二分图中的最大匹配数等于这个图中的最小点覆盖数

什么是最小点覆盖数?

每个点覆盖以他为端点的所有边,选择最少的点来覆盖所有的边,这些点个个数就叫做最小点覆盖数

(选最少点海王,能联系到其他的所有的海王

这里就不证明了,下次一定下次一定(bushi

Girls and Boys

题目描述:

和上面那个差不多,这里说的是两个人之间有个"romantically involved"的亲密关系,让你找到一个集合,使得所有点没有联系,就是求最大独立集。

思路:

最大独立集 = 点总数 - 最大匹配数

我这里使用的是链式前向星建图法

注意⚠️:链式前向星是存边,所以得开大一点的空间,顺便吐槽一下hduoj,数组开的不够大你居然爆TLE,而不是RE,害我我debug一个点都不知道哪里有问题,重写一遍才意识到,可恶至极!

#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<sstream>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define MAX 500 + 50
#define mod 1000000007
#define lowbit(x) (x & (-x))
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d %d",&n,&m)
#define pd(n) printf("%d\n", (n))
#define pdd(n,m) printf("%d %d\n",n, m)
#define sddd(n,m,z) scanf("%d %d %d",&n,&m,&z)
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
typedef unsigned long long ull;
//不开longlong见祖宗!不看范围见阎王!
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}int k, n, m, x, ans, tot;
int link[MAX];
bool vis[MAX];
int head[MAX];
struct ran{int to, next;
}tr[100005];
string s;
char y;void add(int u, int v){//链式前向星建图tr[++tot].to = v;tr[tot].next = head[u];head[u] = tot;
}bool dfs(int u){for(int i = head[u]; i != -1; i = tr[i].next){int v = tr[i].to;if(!vis[v]){vis[v] = 1;if(link[v] == -1 || dfs(link[v])){link[v] = u;return true;}}}return false;
}void init(){//多组输入,一定要记得初始化mem(link, -1);mem(head, -1);ans = tot = 0;
}int main(){while (cin>>n) {init();for(int i = 0; i < n; ++i){cin>>s;cin>>y>>k>>y;//这个题的读入真傻逼,奇奇怪怪的while (k--) {sd(x);add(i, x);}}for(int i = 0; i < n; ++i){mem(vis, 0);if(dfs(i))++ans;}cout<<n - ans/ 2<<endl;}  return 0;
}

The Accomodation of Students

题目描述:

有一群学生,一些人可能彼此认识,一些人可能不认识,认识不存在传染性,如A认识B,B认识C,但A不能就此认识C

你需要将所有学生分成两组,同一组的学生互不认识,如果可以的话,再将认识的两个人放在一个房间里,问最多能需要多少个房间;如果不能就输出No

思路

这个题首先要判能不能构成二分图

如果可以构成,再继续使用匈牙利算法去进行二分图最大匹配

这次用的是邻接矩阵的建图方法

#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<sstream>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define MAX 200 + 50
#define mod 1000000007
#define lowbit(x) (x & (-x))
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d %d",&n,&m)
#define pd(n) printf("%d\n", (n))
#define pdd(n,m) printf("%d %d\n",n, m)
#define sddd(n,m,z) scanf("%d %d %d",&n,&m,&z)
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef  long long ll ;
typedef unsigned long long ull;
//不开longlong见祖宗!提交不看数据范围见祖宗!
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}int n, m, x, y;
bool vis[MAX];
int tr[MAX][MAX];
int co[MAX];
int link[MAX];bool bfs(){queue<int>q;q.push(1);co[1] = 1;while (!q.empty()){int u = q.front();q.pop();for(int i = 1; i <= n; ++i){if(tr[u][i]){if(!co[i]){co[i] = co[u] == 1 ? 2 : 1;q.push(i);}else if(co[i] == co[u])return false;}}}return true;
}bool dfs(int u){for(int i = 1; i <= n; ++i){if(!vis[i] && tr[u][i]){vis[i] = 1;if(!link[i] || dfs(link[i])){link[i] = u;return true;}}}return false;
}void init(){mem(tr, 0);mem(link, 0);mem(co, 0);
}int main(){while (sdd(n, m) != EOF) {init();while (m--) {sdd(x, y);tr[x][y] = 1;}if(!bfs() || n == 1)cout<<"No\n";//n=1有坑!else{int ans = 0;for(int i = 1; i <= n; ++i){mem(vis, 0);if(dfs(i))++ans;}cout<<ans<<endl;}}return 0;
}

匈牙利算法——海王们的渣男渣女行为相关推荐

  1. 点标记 高德地图_打尽渣男渣女的查岗神器?高德家人地图实测

    从「高考防堵」攻略到「积水提醒」功能,再到「实时对讲」导航,高德地图在7月份接连推出了好几个新功能.其中备受关注的,莫过于上周"低调"上线「家人地图」功能.一上线微博又双叒炸开了锅 ...

  2. 高德推出查岗功能_打尽渣男渣女的查岗神器?高德家人地图实测

    从「高考防堵」攻略到「积水提醒」功能,再到「实时对讲」导航,高德地图在7月份接连推出了好几个新功能. 其中备受关注的,莫过于上周"低调"上线「家人地图」功能.一上线微博又双叒炸开了 ...

  3. 有时间同情渣男傻女,不如想想人都是怎么被臆想出来的爱情给坑了

    第184原创 文|明玥 1 整个周末,整个互联网社交环境都被某大叔男明星的丑闻弄得乌烟瘴气. 这么恶心的瓜,我原本并不想吃. 因为细究一下,你就会发现,这个里面没有谁是值得站的,每个人都经不起推敲. ...

  4. 微信内测版更新!微信渣男渣女版上线~

    最近聊哥看到一个消息,微信内测版更新了, 其中还最重要的更新是语音终于有进度条了?? 然而幸福来得很突然,走的也十分突然 猝不及防的,微信官方就辟谣说:"没有的事". 不过,微信进 ...

  5. 【干货+福利】情侣、基友、渣男和狗-基于SynchroTrap+LPA算法的团伙账户挖掘

    本文目的:把经常一起行动的人找出来,并划分成一个Group,仅利用时间关系,无需其他介质 上一期的文章,没有解决相隔时间近但是不在同一个5min切片内的的问题,为了解决这个问题,我研究了一些关于时序的 ...

  6. 上映 10 天,票房就突破 10 亿的《海王》真的有那么好看?

    出品:CSDN(ID:CSDNnews) 写在前面 本文将主要通过Python加上一些数据分析,来证明<海王>好看. <海王>一部电影带你重温<驯龙高手><变 ...

  7. 好家伙,渣男基因被发现了?还能让直男变弯?

    导读:"渣男基因被发现了!"这是怎么回事呢? 作者:宛平城外的胖子 来源:大数据DT(ID:hzdashuju) 01 渣男的必要条件:D4DR基因 上世纪末,耶路撒冷的理查德·埃 ...

  8. 《JS玩算法系列》海王的鱼塘

    这是大冰块2021年第3篇原创文章,和大冰块一起在前端领域努力吧!!! 写在前面 不知为什么,感觉2020年面试过程中算法题突然流行了起来,不论你是前端后端还是架构师,面试前都得先来两道算法题热热身. ...

  9. Kiner算法刷题记(十四):数据结构中的“渣男”——单调栈(数据结构基础篇)

    系列文章导引 系列文章导引 开源项目 本系列所有文章都将会收录到GitHub中统一收藏与管理,欢迎ISSUE和Star. GitHub传送门:Kiner算法算题记 知识回顾 我们之前讨论过单调队列,知 ...

最新文章

  1. date new 转换时区_Pandas 时间序列 时区控制
  2. java collections读书笔记(4) stack
  3. pythone函数基础(11)读,写,修改EXCEL
  4. 微型计算机应用领域及应用,自考“微型计算机应用基础”自考大纲(1)
  5. 【Java】springboot学习笔记二
  6. python3.3psutil模块安装_详解Python3.6安装psutil模块和功能简介
  7. java项目实战之404错误原因总结
  8. 华硕H81M-CT主板开机报USB Device over current status Detected,15秒后关机维修一例
  9. 浙江大学深蓝质感简约答辩PPT模板
  10. 机电工程学院互联网+特色专业17级顶岗实习欢送会​圆满落幕
  11. java 栅栏_Java并发基础-栅栏(CountDownLatch)与闭锁(CyclicBarrier)
  12. 硬货专栏 |WebRTC SDP 详解和剖析
  13. 北塔曾经很张狂 如今沉默为哪桩
  14. YYLabel的几个实用小技巧
  15. C# chart控件中游标随着鼠标移动
  16. 仿网易云音乐app tab栏滑动效果
  17. 数据库大作业代码展示2
  18. 微信小程序接入Vant Weapp
  19. 计算机网络常见问题归纳
  20. 题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

热门文章

  1. Android 遇到的错
  2. Wireshark抓取QQ数据包实例分析
  3. ROS软路由的基本操作(三)
  4. Win8 HTML5与JS编程学习笔记(一)
  5. 天猫团队开源跨平台模块化 UI 界面开发框架 Tangram
  6. PHP内核的存储机制(分离/改变)
  7. #python装饰器(*****)
  8. 2011年1月底的告白
  9. Linux resume流程
  10. 这篇文章搞定你关于Origin Pro的所有问题!快来看看吧!