二分图二•二分图最大匹配之匈牙利算法

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

上一回我们已经将所有有问题的相亲情况表剔除了,那么接下来要做的就是安排相亲了。因为过年时间并不是很长,所以姑姑希望能够尽可能在一天安排比较多的相亲。由于一个人同一天只能和一个人相亲,所以要从当前的相亲情况表里选择尽可能多的组合,且每个人不会出现两次。不知道有没有什么好办法,对于当前给定的相亲情况表,能够算出最多能同时安排多少组相亲呢?

同样的,我们先将给定的情况表转换成图G=(V,E)。在上一回中我们已经知道这个图可以被染成黑白两色。不妨将所有表示女性的节点记为点集A,表示男性的节点记为点集B。则有A∪B=V。由问题可知所有边e的两个端点分别属于AB两个集合。则可以表示成如下的图:

同样的,我们将所有的边分为两个集合。集合S和集合M,同样有S∪M=E。边集S表示在这一轮相亲会中将要进行的相亲,边集M表示在不在这一次进行。对于任意边(u,v) ∈ S,我们称u和v为一组匹配,它们之间相互匹配。在图G,我们将边集S用实线表示,边集M用虚线表示。得到下图:

则原问题转化为,最多能选择多少条边到集合S,使得S集合中任何两条边不相邻(即有共同的顶点)。显然的,|S|<=Min{|A|, |B|}。

那么能不能找到一个算法,使得能够很容易计算出尽可能多的边能够放入集合S?我们不妨来看一个例子:

对于已经匹配的点我们先不考虑,我们从未匹配的点来做。这里我们选择A集合中尚未匹配的点(A3和A4)考虑:

对于A3点,我们可以发现A3与B4右边相连,且都未匹配。则直接将(A3,B4)边加入集合S即可。

对于A4点,我们发现和A4相连的B3,B4点都已经匹配了。但是再观察可以发现,如果我们将A2和B2相连,则可以将B3点空出来。那么就可以同时将(A2,B2),(A4,B3)相连。将原来的一个匹配变成了两个匹配。

让我们来仔细看看这一步:我们将这次变换中相关联的边标记出来,如下图所示紫色的3条边(A2,B2),(A2,B3),(A4,B3)。

这三条边构成了一条路径,可以发现这条路径有个非常特殊的性质。虚线和实线相互交错,并且起点和终点都是尚未匹配的点,且属于两个不同的集合。我们称这样的路径为交错路径。

再进一步分析,对于任意一条交错路径,虚线的数量一定比实线的数量多1。我们将虚线和实线交换一下,就变成了下面的图:

在原来1个匹配的基础上,我们得到了2个新的匹配,S集合边的数量也增加了1。并且原来在已经匹配的点仍然是已经匹配的状态。

再回头看看A3点匹配时的情况:对于(A3,B4)这一条路径,同样满足了交错路径的性质。

至此我们得到了一个找新匹配的有效算法:

选取一个未匹配的点,查找是否存在一条以它为起点的交错路径。若存在,将该交错路径的边虚实交换。否则在当前的情况下,该点找不到可以匹配的点。

又有对于已经匹配的点,该算法并不会改变一个点的匹配状态。所以当我们对所有未匹配的点都计算过后,仍然没有交错路径,则不可能找到更多的匹配。此时S集合中的边数即为最大边数,我们称为最大匹配数。

那么我们再一次梳理整个算法:

1. 依次枚举每一个点i; 
2. 若点i尚未匹配,则以此点为起点查询一次交错路径。

最后即可得到最大匹配数。

在这个基础上仍然有两个可以优化的地方:

1.对于点的枚举:当我们枚举了所有A中的点后,无需再枚举B中的点,就已经得到了最大匹配。
2.在查询交错路径的过程中,有可能出现Ai与Bj直接相连,其中Bj为已经匹配的点,且Bj之后找不到交错路径。之后又通过Ai查找到了一条交错路径{Ai,Bx,Ay,…,Az,Bj}延伸到Bj。由于之前已经计算过Bj没有交错路径,若此时再计算一次就有了额外的冗余。所以我们需要枚举每个Ai时记录B集合中的点是否已经查询过,起点不同时需要清空记录

输入

第1行:2个正整数,N,M(N表示点数 2≤N≤1,000,M表示边数1≤M≤5,000)
第2..M+1行:每行两个整数u,v,表示一条无向边(u,v)

输出

第1行:1个整数,表示最大匹配数

样例输入
5 4
3 2
1 3
5 4
1 5
样例输出
2
 
 
思考:如果是在无向图(并非树,不能树形DP做)中选择最多的边,使得这些边的顶点不相交。
不能染色,毕竟不一定满足check后不是男就是女。这样是否是NP问题。
 
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=;
const int maxm=;
int Laxt[maxm],Next[maxm],To[maxm],cnt;
int linke[maxn],vis[maxn],col[maxn],n;
void add(int u,int v)
{
Next[++cnt]=Laxt[u];
Laxt[u]=cnt;
To[cnt]=v;
}
int read()
{
char c=getchar();int s=;
while(c>''||c<'') c=getchar();
while(c>=''&&c<=''){s=s*+c-'';c=getchar();}
return s;
}
bool find(int u)
{ for(int i=Laxt[u];i;i=Next[i]){
int v=To[i];
if(vis[v]||col[v]==) continue;
vis[v]=;
if(!linke[v]||find(linke[v])){
linke[v]=u;
return true;
}
}
return false;
}
bool dfs(int v,int c)
{
for(int i=Laxt[v];i;i=Next[i]){
if(col[To[i]]==c) return false;
if(!col[To[i]]){
col[To[i]]=-c;
if(!dfs(To[i],-c)) return false;
}
}
return true;
}
bool check()
{
for(int i=;i<=n;i++){
if(col[i]) continue;
col[i]=;
if(!dfs(i,)) return false;
}
return true;
}
int main()
{
int m,i,u,v,ans=;
scanf("%d%d",&n,&m);
for(i=;i<=m;i++) {
u=read();v=read();
add(u,v);
add(v,u);
}
check();
for(i=;i<=n;i++){
if(col[i]==) {
memset(vis,,sizeof(vis));
if(find(i)) ans++;
}
}
printf("%d\n",ans);
return ;
}

HihoCoder 1122二分图二 ---最大匹配之匈牙利算法的更多相关文章

  1. [hihoCoder] #1122 : 二分图二•二分图最大匹配之匈牙利算法

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一回我们已经将所有有问题的相亲情况表剔除了,那么接下来要做的就是安排相亲了.因为过年时间并不是很长,所以姑姑希望能够尽可 ...

  2. hihocoder #1122 二分图二•二分图最大匹配之匈牙利算法(*【模板】应用 )

    梳理整个算法: 1. 依次枚举每一个点i: 2. 若点i尚未匹配,则以此点为起点查询一次交错路径. 最后即可得到最大匹配数. 在这个基础上仍然有两个可以优化的地方: 1.对于点的枚举:当我们枚举了所有 ...

  3. 【hihocoder 1122】二分图二•二分图最大匹配之匈牙利算法

    [Link]:https://hihocoder.com/problemset/problem/1122 [Description] [Solution] 二分图匹配,匈牙利算法模板题; 这里我先把染 ...

  4. 二分图最大匹配:匈牙利算法的python实现

    二分图匹配是很常见的算法问题,一般用匈牙利算法解决二分图最大匹配问题,但是目前网上绝大多数都是C/C++实现版本,没有python版本,于是就用python实现了一下深度优先的匈牙利算法,本文使用的是 ...

  5. 51nod 2006 飞行员配对(二分图最大匹配) 裸匈牙利算法 求二分图最大匹配题

    题目: 题目已经说了是最大二分匹配题, 查了一下最大二分匹配题有两种解法, 匈牙利算法和网络流. 看了一下觉得匈牙利算法更好理解, 然后我照着小红书模板打了一遍就过了. 匈牙利算法:先试着把没用过的左 ...

  6. "《算法导论》之‘图’":不带权二分图最大匹配(匈牙利算法)

    博文“二分图的最大匹配.完美匹配和匈牙利算法”对二分图相关的几个概念讲的特别形象,特别容易理解.本文介绍部分主要摘自此博文. 还有其他可参考博文: 趣写算法系列之--匈牙利算法 用于二分图匹配的匈牙利 ...

  7. 二分图最大匹配(匈牙利算法)简介& Example hdu 1150 Machine Schedule

    二分图匹配(匈牙利算法) 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数.如果你还不知 ...

  8. 【模板】二分图最大匹配(匈牙利算法)/洛谷P3386

    题目链接 https://www.luogu.com.cn/problem/P3386 题目大意 给定一个二分图,其左部点的个数为 \(n\),右部点的个数为 \(m\),边数为 \(e\),求其最大 ...

  9. 无权二分图最大匹配 HDU2063 匈牙利算法 || Hopcroft-Karp

    参考两篇比较好的博客 http://www.renfei.org/blog/bipartite-matching.html http://blog.csdn.net/thundermrbird/art ...

随机推荐

  1. nodejs的http.request使用post方式提交数据请求

    官方api文档 http://nodejs.org/docs/v0.6.1/api/http.html#http.request虽然也有POST例子,但是并不完整. 直接上代码:http_post.j ...

  2. java synchronized和(ReentrantLock)区别

    原文:http://blog.csdn.net/zheng548/article/details/54426947 区别一:API层面 syschronized使用 synchronized即可修饰方 ...

  3. js 科学计数法

    function convertNum(num_str){ //参数必须为 字符串 //科学计数法字符 转换 为数字字符, 突破正数21位和负数7位的Number自动转换 // 兼容 小数点左边有多位 ...

  4. hadoop07---synchronized,lock

    synchronized 锁是jvm控制的,控制锁住的代码块只能有一个线程进入.线程执行完了锁自动释放,抛出异常jvm会释放锁. synchronized的缺陷 1.如果一个线程被阻塞了,其余的线程 ...

  5. sq 如何创建全局的临时表。

    全局临时表的生命周期一直持续到创建会话(不是创建级别)才终止.例如,如果你在存储过程中创建全局临时表,当超出存储过程的范围时,该表并不会被销毁.当创建会话终止后,SQL Server才会自动尝试删除该 ...

  6. 20145201 《Java程序设计》第二周学习总结

    20145201 <Java程序设计>第二周学习总结 教材学习内容总结 本周学习了课本第三章内容,即JAVA基础语法. 3.1 类型.变量与运算符 基本类型:在java中基本类型主要可区分 ...

  7. openstack认证实践

    环境: 客户端:负责发送请求, 服务器:负责接受请求: 认证服务器keystone:负责认证 具体认证步骤: 1.客户端首先进行签名计算,将得到的签名字符串作为authorization发给keyst ...

  8. setState详解

    我们都知道,React通过this.state来访问state,通过this.setState()方法来更新state.当this.setState()方法被调用的时候,React会重新调用rende ...

  9. windows 下android react native详细安装配置过程

    写在前面: 在网上搜了很多安装配置文档,感觉没有一个真的跟我安装的过程一模一样的,东拼拼西凑凑,总算是装好了,我不会告诉你,断断续续,我花了两天时间...一到黑屏报错就傻眼,幸好在react群里遇到了 ...

  10. 在Linux系统下使用Github的基本教程

    1. 安装git: sudo apt-get install git-core git-gui git-doc 2.到https://github.com/ 注册一个帐号,一会儿客户端登录的时候要使用 ...