ACM二分图基础
ACM算法分类
经过我初步的整理,一个比较完整的归类已经完成,现在发布给大家,希望可以方便大家练习,如有不足,还请大家见谅,这个可能会随时有更新,请大家注意.如果有什么要求或补充的可以跟贴提出,勿水!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
OJ上的一些水题(可用来练手和增加自信)
(poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094)
初期:
一.基本算法:
(1)枚举. (poj1753,poj2965)
(2)贪心(poj1328,poj2109,poj2586)
(3)递归和分治法.
(4)递推.
(5)构造法.(poj3295)
(6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)
二.图算法:
(1)图的深度优先遍历和广度优先遍历.
(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)
(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)
(3)最小生成树算法(prim,kruskal)
(poj1789,poj2485,poj1258,poj3026)
(4)拓扑排序(poj1094)
(5)二分图的最大匹配(匈牙利算法) (poj3041,poj3020)
(6)最大流的增广路算法(KM算法). (poj1459,poj3436)
三.数据结构.
(1)串(poj1035,poj3080,poj1936)
图论专题 二分图
图论专题二分图
朝花夕拾2010-12-28 17:56:46 阅读66 评论0 字号:大中小订阅
二分图:二分图是这样一个图,它的顶点可以分类两个集合X和Y,所有的边关联的两个顶点恰好一个属于集合X,另一个属于集合Y。
二分图匹配:给定一个二分图G,在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,则称M是一个匹配。
最大匹配:图中包含边数最多的匹配称为图的最大匹配。
完美匹配:如果所有点都在匹配边上,则称这个最大匹配是完美匹配。
二分图匹配基本概念:
未盖点
设VI是G的一个顶点,如果VI不与任意一条属于匹配M的边相关联,就称VI是一个未盖点。
交错轨
设P是图G的一条轨,如果P的任意两条相邻的边一定是一条属于M而另一条不属于M,就称P是交错轨。
可增广轨(增广路)
两个端点都是未盖点的交错轨称为可增广轨。
可增广轨的性质:
1:P的路径长度必定为奇数,第一条边和最后一条边都不属于M。
2:P经过取反操作可以得到一个更大的匹配M’。
3:M为G的最大匹配当且仅当不存在相对于M的增广路径。
二分图最大匹配匈牙利算法:
算法的思路是不停的找增广轨,并增加匹配的个数,增广轨顾名思义是指一条可以使匹配数变多的路径,在匹配问题中,增广轨的表现形式是一条"交错轨",也就是说这条由图的边组成的路径,它的第一条边是目前还没有参与匹配的,第二条边参与了匹配,第三条边没有..最后一条边没有参与匹配,并且始点和终点还没有被选择过.这样交错进行,显然他有奇数条边.那么对于这样一条路径,我们可以将第一条边改为已匹配,第二条边改为未匹配...以此类推.也就是将所有的边进行"取反",容易发现这样修改以后,匹配仍然是合法的,但是匹配数增加了一对.另外,单独的一条连接两个未匹配点的边显然也是交错轨.可以证明,当不能再找到增广轨时,就得到了一个最大匹配.这也就是匈牙利算法的思路。
ACM都要学什么
ACM都要学什么
今天查资料发现了一份做ACM需要知道的知识的表,仔细看了看发现初级竟然还有这么大一部分不会,发现需要学的东西还有这么多。以后要加速了。初步计划一个半月在保证ACM学习小组进度和C#考试的基础上先把初级的全刷一遍,脱离菜鸟级别。
初期:
一.基本算法:
(1)枚举. (poj1753,poj2965)
(2)贪心(poj1328,poj2109,poj2586)
(3)递归和分治法.
(4)递推.
(5)构造法.(poj3295)
(6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)
二.图算法:
(1)图的深度优先遍历和广度优先遍历.
(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)
(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)
(3)最小生成树算法(prim,kruskal)
(poj1789,poj2485,poj1258,poj3026)
(4)拓扑排序(poj1094)
(5)二分图的最大匹配(匈牙利算法) (poj3041,poj3020)
(6)最大流的增广路算法(KM算法). (poj1459,poj3436)
三.数据结构.
(1)串(poj1035,poj3080,poj1936)
(2)排序(快排、归并排(与逆序数有关)、堆排) (poj2388,poj2299)
(3)简单并查集的应用.
(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)
ACM基础——图
(6)稠密图、稀疏图 边数很少的图称为稀疏图,反之称为稠密图。
(7)顶点的度 无向图中为依附于某顶点v的边数, 记为TD(v)。 在有向图中,分为顶点的入度与出 度。 顶点v的入度:以顶点v为终点的弧 的数目,记为ID(v)。 顶点v的出度:以顶点v为始点的弧 的数目,记为OD(v)。 TD(v)=ID(v)+OD(v)。 对于具有n个顶点、e条边的图,顶 点vi的度TD(vi)与顶点的个数以及边的 数目满足关系: n e * 2 = ∑ TD(vi)
Status CreateALG(ALGraph &G){ int i,j,k,v1,v2; ArcNode *L; scanf("%d%d",&G.vexnum,&G.arcnum); for(i=0;i<G.vexnum;i++){ scanf("%d",&G.vertices[i].data); G.vertices[i].firstarc=NULL; } for(k=0;k<G.arcnum;k++){ scanf("%d%d",&v1,&v2); i=LocateVex(G,v1); j=LocateVex(G,v2); L = (ArcNode *)malloc(sizeof(ArcNode)); L->adjvex=j; L->nextarc=G.vertices[i].firstarc; G.vertices[i].firstarc=L; /*建逆邻接表 L = (ArcNode *)malloc(sizeof(ArcNode)); L->adjvex=i; L->nextarc=G.vertices[j].firstarc; G.vertices[j].firstarc=L; */ } return OK; }
天津大学ACMICPC暑期集训讲座 二分图匹配
寻找交错链
1
1
2
2
3
3
4
4
h
16
寻找交错链的算法
1,从左某一个未被匹配的点开始寻找,把 所有与它相连的点加进队列
2,如果在右边找到一个未被匹配的点,则 算法结束
3,如果在右边找到一个已经被匹配了的点, 则看看它是与左边的哪个点相匹配的,从 相匹配的那个点出发在右边找点,把它们 加入队列
可以通过更改交错链上的边来获取更大的 匹配
2.如果我们找到了一个匹配,并且再也 找不到交错链了,那么这个匹配是最大匹 配
h
9
匈牙利算法
匈牙利算法的思路就是:不停地在一个二 分图中寻找交错链,直到找不到为止。
寻找交错链可以用BFS或DFS,其中BFS效 率很高,但实现较复杂。
h
10
寻找交错链的算法
每个人只能做一份工作,每个工作岗位也 只需要一个人
h
2
二分图的一般表述
一个图的点,可以分割成两个集合X和Y 在集合内部没有边 任何一条边的两个端点都分属不同的集合
h
3
匹配
在工作分配的问题中,我们给出一个可行 的分配方案,就是一个匹配。如果这个匹 配是最优的(可以填补的工作岗位最多), 就是最大匹配。
能深入了解算法,可以先搞清楚它可以解 决哪些问题,遇到此类问题只要套上模板 就可以AC
acm竞赛知识点
acm竞赛知识点
以下是ACM竞赛的主要知识点:
1、基础算法:
排序算法(如快速排序、归并排序)
搜索算法(如二分搜索)
递归与分治算法
2、图论:
最短路径算法(如Dijkstra算法、Bellman-Ford算法)最小生成树算法(如Prim算法、Kruskal算法)
拓扑排序
图的遍历(深度优先搜索DFS、广度优先搜索BFS)
3、动态规划:
背包问题
最长公共子序列(LCS)
最长递增子序列(LIS)
矩阵链乘法
4、数据结构:
栈和队列
链表和树的基本操作
哈希表
并查集
5、计算几何:
点和向量的基本运算
线段相交判定
凸包算法
6、字符串处理:
字符串匹配算法(如KMP、Boyer-Moore)后缀数组
字符串编辑距离
7、数论:
质数判定
最大公约数和最小公倍数
快速幂
8、图的高级算法:
最大流算法(如Ford-Fulkerson算法)二分图匹配
最小割算法
9、动态规划优化:状态压缩
斜率优化
记忆化搜索
10、其他:
模拟和贪心算法
数学问题
网络流问题
ACM必要的算法合集---队员常备
*KM 算法 匈牙利算法
1.7 数学相关
1. (扩展)欧几里得算法,筛法,快速幂 斐蜀定理 更相减损术
2. 欧拉函数与*降幂大法 3. 费马小定理 4. 排列组合
lucas 定理 5. 乘法逆元 6. 矩阵乘法 7. 数学期望与概率
8. 博弈论 sg 函数 树上删边游戏
1.1 基本数据结构
1. 数组 2. 链表,双向链表 3. 队列,单调队列,双端队列 4. 栈,单调栈
1.2 中级数据结构
1. 堆 2. 并查集与带权并查集 3. hash 表
自然溢出 双 hash
1.3 高级数据结构
1. 树状数组 2. 线段树,线段树合并 3. 平衡树
Treap 随机平衡二叉树 Splay 伸展树 * Scapegoat Tree 替罪羊树 4. 块状数组,块状链表 5.* 树套树 线段树套线段树 线段树套平衡树 * 平衡树套线段树 6.可并堆 左偏树 *配对堆 7. *KDtree,*四分树
1.4 可持久化数据结构
1. 可持久化线段树 主席树
2. * 可持久化平衡树 3. * 可持久化块状数组
1.5 字符串相关算法及数据结构
1. KMP 2. AC 自动机 3. 后缀数组 4. *后缀树 5. *后缀自动机 6. 字典树 Trie
7. manacher
杭电acm的利用
此次培训主要锻炼同学们的算法学习,更重要的是锻炼同学们的自学能力,对于我们学计算机的同学来说,自学能力是关键,如果你真的指望从老师那里学到什么的话。。。。。。。。。。。。。。。(千万不能告诉老师)所以,这个真的很关键,首先是独立思考问题的能力,我对同学们的要求是,如果同学们遇到了问题,至少独立思考1小时以上,才可以从网上找答案或者问别人。不要觉得这个要求苛刻,其实这是一个很好的方法,如果一遇到不会的难题就上网查或者问,虽然可能题一会做出来了,但是下次碰见还是不会,甚至根本就没有印象。我经常调试程序3、4个小时以上,偶尔都会有10个小时的调试。这对同学们日后的学习很有帮助。
第一阶段:开始入门吧!(15天,53题)一.输入输出练习(2天,10题)
1000、1089—1096、1001
二.简单操作:(2—4天,12题)
2000—2011、2039
三.英文题试水(3—4天,8题)
1720、1062、2104、1064、2734、1170、1197、2629
四.回归水题(4-6天,24题)
2012—2030、2032、2040、2042、2054、2055
(第一阶段大体结束之后,会由几位学长讲一些数据结构的知识,请同学们务必跟上进度!)第二阶段:我要学算法!(12天,31题)
一.字符串我要会处理(2天,6题)
2072、2081、2093、2091、1004、2057
二.简单数学题(4天,12题)
2031、2033、2070、2071、2075、2089、2090、2092、2096—2099
acm程序设计竞赛 数学基础 刘汝佳
数学基础(版本2009)
刘汝佳
例1. 同构计数
•一个竞赛图是这样的有向图
–任两个不同的点u、v之间有且只有一条边
–不存在自环
•用P表示对竞赛图顶点的一个置换。当任两个不同顶点u、v间直接相连的边的方向与顶点P(u)、P(v)间的一样时,称该图在置换P下同构
•对给定的置换P,我们想知道对多少种竞赛图在置换P下同构
分析
•先把置换它分解成为循环, 首先证明长度为L的偶循环将导致无解
–对于点i1, 记P(i k)=i k+1, 假设i1和i L/2+1的边方向为
i1->i L/2+1, 那么有i2->i L/2+2, i3->i L/2+3, …, i L/2+1->i1, 和假设矛盾!
•假设确定其中k条独立边后其他边也会确定, 则答案为2k
•考虑两类边: 循环内边和循环间边.
分析
•循环内顶点的关系
–定了i 1和i j 之间的关系, i k 与i (k+j-2) mod n+1之间的关系也被确定下来了, 因此只需要确定i 1和i 2, i 3, …, i (L-1)/2+1这(L-1)/2对顶点的关系
•不同循环间顶点的关系
–设循环为(i 1,i 2,…,i L1)和(j 1,j 2,…,j L2), 通过类似分析得只需要确定gcd(L1, L2)对关系即可
分析
•最后答案为2k1+k2
•其中k1=sum{(L-1)/2}, k2=sum{gcd(L1, L2)}•可以用二分法加速求幂
例2. 图形变换
•平面上有n个点需要依次进行m个变换处理
•规则有4种, 分别把(x
0,y
ACM 程序设计竞赛入门:第10讲 二分图
2020/12/10
13
图示(3):
女1 男1
男2
返回
2020/12/10
女2
X0=男2 V1={男2} V2 = Φ T(V1)={女1} T(V1) != V2
Y=女1 V1={男2,男1} V2 ={女1}
T(V1)=V2
14
NOTE:
真正求二分图的最 大匹配的题目很少 ,往往做一些简单 的变化,比如——
明的思想,其基本步骤为:
1.任给初始匹配M; 2.若X已饱和则结束,否则进行第3步; 3.在X中找到一个非饱和顶点x0,
作V1 ← {x0}, V2 ← Φ; 4.若T(V1) = V2则因为无法匹配而停止,否 则任选一点y ∈T(V1)\V2; 5.若y已饱和则转6,否则做一条从x0 →y的 可增广道路P,M←M⊕E(P),转2; 6.由于y已饱和,所以M中有一条边(y,z),作 V1 ← V1 ∪{z}, V2 ← V2 ∪ {y}, 转4;
2020/12/10
Biblioteka Baidu
15
变种1: 二分图的最小顶点覆盖
在二分图中求最少的点,让每条边都至少和其 中的一个点关联,这就是
顶点 小 最 “二分图的
覆盖”
。
2020/12/10
16
实例分析
2020/12/10
17
ACM常用模板 二分图最佳匹配(kuhn_munkras
//二分图最佳匹配,kuhn munkras算法,邻接阵形式,复杂度O(m*m*n)//返回最佳匹配值,传入二分图大小m,n和邻接阵mat,表示权值//match1,match2返回一个最佳匹配,未匹配顶点match值为-1//一定注意m<=n,否则循环无法终止//最小权匹配可将权值取相反数#include #define MAXN 310#define inf 1000000000#define _clr(x) memset(x,0xff,sizeof(int)*n)int kuhn_munkras(int m,int n,int mat[][MAXN],int* match1,int* match2){int s[MAXN],t[MAXN],l1[MAXN],l2[MAXN],p,q,ret=0,i,j,k;for (i=0;ifor (l1[i]=-inf,j=0;jl1[i]=mat[i][j]>l1[i]?mat[i][j]:l1[i];for (i=0;ifor (_clr(match1),_clr(match2),i=0;ifor (_clr(t),s[p=q=0]=i;p<=q&&match1[i]<0;p++)for (k=s[p],j=0;jif (l1[k]+l2[j]==mat[k][j]&&t[j]<0){s[++q]=match2[j],t[j]=k;if (s[q]<0)for (p=j;p>=0;j=p)match2[j]=k=t[j],p=match1[k],match1[k]=j;}if (match1[i]<0){for (i--,p=inf,k=0;k<=q;k++)for (j=0;jif (t[j]<0&&l1[s[k]]+l2[j]-mat[s[k]][j]p=l1[s[k]]+l2[j]-mat[s[k]][j];for (j=0;jfor (k=0;k<=q;l1[s[k++]]-=p);}}for (i=0;iret+=mat[i][match1[i]];return ret;}
ACM算法讲解
约5% 约10% 其它 约25%
5
纯数学题 数据结构
图作为一种非线性结构,被广泛应用于多个技术 领域。这一部分将是最难理解的,我们将先从基础知 识的讲解开始。
6
图论相关主题
• • • • • 第一阶段——图的遍历 第二阶段——最小生成树 第三阶段——最短路径 第四阶段——关键路径 第五阶段——拓扑排序
7
主题一、图的遍历
从图中的某个顶点出发,按某种方法对图中的 所有顶点访问且仅访问一次。
作用:是求解图的连通性问题、拓扑排序和求 关键路径等算法的基础。 为了保证图中的各顶点在遍历过程中访问且仅 访问一次,需要为每个顶点设一个访问标志,用以 标示图中每个顶点是否被访问过,访问标志用数组 visited[n]来表示。
8
深度优先搜索 图的遍历方法有两种: 广度优先搜索
9
深度优先搜索(DFS)——使用栈
深度优先搜索(Depth_First Search)是指按照深度 方向搜索 ,它类似于树的先根遍历。
深度优先算法的基本思想是:
(1)从图中某个顶点v0出发,首先访问v0。
(2)找出刚访问过的顶点vi的第一个未被访问的邻 接点,然后访问该顶点。重复此步骤,直到当前的 顶点没有未被访问的邻接点为止。 (3)返回前一个访问过的顶点,找出该顶点的下一 个未被访问的邻接点,访问该顶点。转2。
ACM在线训练方法09
四、注意事项
1、遇到困难很正常。 (1)编程慢。牛人一小时做一道题,哪怕我三、四天做出来,也很棒。毕竟在起步阶段。 (2)英语麻烦。这些英语语法不难,再偶尔查单词,就可以搞定。1 周就可以比较熟悉。 (3)所用知识未学习。在基础数据结构和基础算法之上,还有很多高级的“拳法”。这 些如果我们不自学,本科阶段几乎无法接触到。另一方面,有了基础后,这些知识很容易 学习的。 2、踏实。ACM 题集的前半部分上线较久,为很多人很多年研究,网上能够找到解答 和解释说明。不能提交上就完事,要自己理解了、独自敲出来才算过。 3、系统允许多次提交相同的题目。侥幸通过的题目,应该再体会、再练。 4、不要耽误正常上课和训练课程的其他要求。 5、编程关还差得较远的(例如:数据结构理解不好,数量掌握的排序算法<3 个,尚未 掌握调试程序的方法),更不要着急。可以适当调整自己,仍从基础来。 6、注意 judge on line 系统的使用细节,以免犯低级错误。例如,提交代码时注意语言 的选择。 7、必须严格遵守题目对 I/O 格式的要求,程序才能被接受。可以借鉴课件中曾经讲过 的 I/O 模板。
附 1:POJ 问题分类,训练的主要参考列表 (题目的难度不一,请选择学习。如遇某单元 的例问题过于复杂或自学有困难,可以在后 面的 4 个附录中选择适当题目。)
一.基本 算法
初级
(1)枚举 (2)贪心 (3)递归和分治法 (4)递推 (5)构造法
ACM资料
ACM大量习题题库 收藏 ACM大量习题题库 现在网上有许多题库,大多是可以在线评测,所以叫做Online Judge。除了USACO是为IOI准备外,其余几乎全部是大学的ACM竞赛题库。USACO/usacogate美国著名在线题库,专门为信息学竞赛选手准备TJU/同济大学在线题库,唯一的中文题库,适合NOIP选手ZJU/浙江大学在线题库JLU/吉林大学在线题库(一直上不去)PKU北京大学在线题库URALhttp://acm.timus.ru俄罗斯乌拉尔大学在线题库SGUhttp://acm.sgu.ru/俄罗斯圣萨拉托夫州大学在线题库ELJhttp://acm.mipt.ru/judge/bin/problems.pl?lang=en俄罗斯莫斯科物理技术学院SPOJhttps://spoj.sphere.pl/波兰格但斯克理工大学UVAhttp://acm.uva.es/西班牙的Universidad de Valladolid在线题ACM联系建议一位高手对我的建议:一般要做到50行以内的程序不用调试、100行以内的二分钟内调试成功.acm主要是考算法的,主要时间是花在思考算法上,不是花在写程序与debug上。 下面给个计划你练练:第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打出来. 1.最短路(Floyd、Dijstra,BellmanFord) 2.最小生成树(先写个prim,kruscal要用并查集,不好写) 3.大数(高精度)加减乘除 4.二分查找. (代码可在五行以内) 5.叉乘、判线段相交、然后写个凸包. 6.BFS、DFS,同时熟练hash表(要熟,要灵活,代码要简) 7.数学上的有:辗转相除(两行内),线段交点、多角形面积公式. 8. 调用系统的qsort, 技巧很多,慢慢掌握. 9. 任意进制间的转换第二阶段:练习复杂一点,但也较常用的算法。 如: 1. 二分图匹配(匈牙利),最小路径覆盖 2. 网络流,最小费用流。 3. 线段树. 4. 并查集。 5. 熟悉动态规划的各个典型:LCS、最长递增子串、三角剖分、记忆化dp 6.博弈类算法。博弈树,二进制法等。 7.最大团,最大独立集。 8.判断点在多边形内。 9. 差分约束系统. 10. 双向广度搜索、A*算法,最小耗散优先.第三阶段:前两个阶段是打基础,第三阶段是锻炼在比赛中可以快速建立模型、想新算法。这就要平时多做做综合的题型了。 1. 把oibh上的论文看看(大概几百篇的,我只看了一点点,呵呵)。 2. 平时扫扫zoj上的难题啦,别老做那些不用想的题.(中大acm的版主经常说我挑简单的来做:-P ) 3. 多参加网
二部图
下找增广路 link[i]=u;//在递归返回过程中不断修改 return 1;
} } } return 0; }
匈牙利算法
访问x3,找到增广路x3->y1->x1->y2->x2>y5,修改y5
x1 x2 x3 x4 x5 x6
y1( y2( y3( y4( y5( y6( y7( x1) x2) -1) -1) x2) -1) -1)
从y5沿路回退修改
x1 x2 x3 x4 x5 x6
匈牙利算法
y1( y2( y3( y4( y5( y6( y7( x3) x1) -1) -1) x2) -1) -1)
x1 x2 x3 x4 x5 x6
y1( y2( y3( y4( y5( y6( y7( x1) -1) -1) -1) -1) -1) -1)
访问x2,和x1类似
x1 x2 x3 x4 x5 x6
匈Βιβλιοθήκη Baidu利算法
y1( y2( y3( y4( y5( y6( y7( x1) x2) -1) -1) -1) -1) -1)
16个ACM经典算法介绍
16个ACM经典算法介绍
一、排序算法:
1.冒泡排序:基于比较的排序算法,通过不断交换相邻元素将最大元
素逐渐向后移动。
2.插入排序:基于比较的排序算法,通过将元素逐个插入到已排好序
的部分中,最终得到完全有序的序列。
3.归并排序:基于分治的排序算法,将待排序序列划分为一系列子序列,然后将子序列进行合并,最终得到完全有序的序列。
4.快速排序:基于分治的排序算法,通过选择一个基准元素将序列划
分为两部分,然后递归地对两部分进行排序。
5.堆排序:基于堆的排序算法,通过构建最大堆或最小堆来实现排序。
二、查找算法:
6.二分查找:基于有序序列的查找算法,通过将待查找值与序列中间
元素进行比较,逐渐缩小查找范围。
7.哈希表:基于哈希函数的查找算法,通过将键值对存储在哈希表中,实现高效的查找。
三、图算法:
8.深度优先(DFS):基于栈的算法,通过递归地访问顶点的邻接顶点,实现图的遍历。
9.广度优先(BFS):基于队列的算法,通过访问顶点的邻接顶点,
实现图的遍历。
10. 最小生成树算法:用来求解无向图的最小生成树,常用的有
Prim算法和Kruskal算法。
11. 最短路径算法:用来求解有向图或带权重的无向图的最短路径,
常用的有Dijkstra算法和Floyd-Warshall算法。
四、动态规划算法:
12.最长上升子序列(LIS):用来求解一个序列中最长严格递增子序
列的长度。
13.背包问题:用来求解在给定容量下,能够装入尽量多的物品的问题。
五、字符串算法:
14.KMP算法:用来在一个文本串S中查找一个模式串P的出现位置
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
这个算法的原理?
• 匈牙利算法通过不断的寻找增广路来寻找最大匹配。 • 什么是增广路? • 增广路:若 P 是图 G 中一条连通两个未匹配顶点的路径,并且 属最大匹配边集 M 的边 和不属 M 的边(即已匹配和待匹配的边) 在 P 上交替出现,则称 P 为相对于 M 的 一条增广轨。
1 4 例如在该图中,假如现在的匹配路径 为1 --> 5 , 2 --> 6 那么路径3-->6-->2-->5-->1-->4就是 一条增广路
• 如果我们对这个图求二分图的最大匹配,你会发现每个匹配对应着一个路径 覆盖,因此,此 二分图的最大匹配即:原图中的最小路径覆盖上的边的个 数(路径是由 0 条,1 条或多条边 组成的) 。那么原图的最小路径覆盖 数 = 原图顶点数 – 最小路径上的边数 也就是 原图的 最小路径覆盖数 = 原图顶点数 – 二分图最大匹配数
如何实现匈牙利算法?
• 我们模拟每个人能否找到小伙伴去打游戏 • 我们只考虑二分图的一个集合 假如是ABC • 我们可以知道 如果B找到了一个增广路 即B最后可以有人陪着一 起打游戏 • 过去已经找到了朋友的人不会受到影响 也许他们换了一个队友 • 但他们仍然会有人一起玩
所以我们这样
• 一开始 没有人被拉走 • A出手了 看到了一个朋友E 一问 她还单身 • 于是A找到了队友 • 所以记录下E被谁拉走了 并且总的匹配数加一 • B也出手了 他看到一个朋友F 一问 她还是单身 • 于是B找到了队友 • 所以记录下F被谁拉走了 并且总的匹配数加一
二分图的判定
• 定理: • 1 图G至少有两个点 // 需要保证XY不是空集 • 2 G中所有的回路的长度都是偶数 • 根据这个定理 在判定一个图是否为二分图的时候只需要进行判断 G中是否存在奇数长度的回路 • 常用的办法是基于BFS的相邻染色法 即对任意一个点进行BFS 如果uv之间有一条边 我们从u访问到v 如果v未被染色 则v将被染 成和u相对的染色 • 如果相邻节点(u和v)是相同颜色 则存在奇回路
那么如果允许每个点经过多次而边只经过 一次呢?
• 我们进行一次floyd算法 就可以得出每个点能到达哪些点 • 然后再建立二分图的时候 将这些直接到达的边也加入
现在我们来讲一下二分图的建模
• 当然接下来很多要讲的 • 在诸位以后这个程度的时候看一眼 就会发现 • 只是一些简单的套路而已 • 但是这些都是十分经典的建模 • 需要多看些时间了解
那么重点就是fin 这个男孩找队友的程序怎么写
• bool fin(int u) • for(int i = 0 ; i < q[u].size() ; i ++ ){ 枚举他认识的所有女孩 int v = q[u][i] if(vis[v] == false) continue ; 这个女孩被问过了 vis[v] = false ; if(linker[v] == -1 || fin(linker[v])) { 这个女孩没有组队||这个女孩的队 友有别的选择 linker[v] = u ; return true ;} } • return false ;
最小边覆盖集
• 边覆盖集 选择一个边集 使所有的点都被覆盖 • 最小边覆盖集 选择最少的边 使所有的点都被覆盖 • 性质 最小边覆盖集 = 最大独立集 = 总点数 - 最大匹配
最小不相交路径
• 在一个有向图中 , 路径覆盖 就是选择一些路径 使所有的点都被 访问了一次 (只有一条路径与之关联) 即 将这些路径从起点走到 终点一次 图中的所有的点都会被访问一次 • 性质 :DAG(有向无环图)的最小不相交路径覆盖数=DAG图中的 节点数-相应二分图中的最大匹配数.
匈牙利算法
• 匈牙利算法用来解决二分图最大匹配问题,首先可以想到的是, 我们可以通过搜索,找出所有的这样的满足上面条件的边集,然 后从所有的边集中选出边数最多的那个集合,但是我们可以感觉 到这个算法的时间复杂度是边数的 指数级函数,因此我们有必 要寻找更加高效的方法。对于点的个数都在 200 到 300 之间的 数据,我们是采取匈牙利算法的,因为匈牙利算法实现起来要比 网络流和HK简单些。
• memset(linker , -1 , sizeof(linker)) ; 一开始所有女孩都没组队 • int ans = 0 ; 匹配数目 • for(int i = 1 ; i <= n ; i ++ ) 枚举所有男孩 • memset(vis, true , sizeof(vis)) ; 对于这个男孩找队友的艰辛路程 所有女孩都还没因为此被问到 • if(fin(i)) 如果这个男孩成功的找到了队友 • ans ++ ;
公式:最大点独立集 = 顶点共个数 - 最大匹配数
证明:(V-2*M+M) Eg: 有n个男生,m个女生,男生之间相互不了解,女生之间相互不了解,然后告诉你一些关 系(i,j)表示男生i与女生j相互了解,问最多能选出多少人,使这些人之中不相互了解。
详细证明
• • • • • • 设最大匹配为M 1 我们先把匹配出的M*2个人拿出V集 剩下的人肯定互相之间不认识 如果有认识的 就可以构成新的匹配 2 我们在匹配的M*2个人中 每对关系都拿出一个人 放回V集 我们如何保证拿回来的人不与剩下的人认识? 如果拿回来的是左边的人 他有右边的认识的人 我们就拿这个关系中右边 的人 • 如果这个人在左边也有认识的人 • 就会发生 -> X • 于是就会多出来一个匹配 这是不存在的
• 而第偶数条边 • 即F->B E->A (其实还是B->F A->E) • 都是已经被确定的关系
所以我们可以总结出一些东西
• 1 增广路 有奇数条边 • 2 它的起点是左集合 终点是右集合 • 3 增广路上的点一定是一个点在左集合 一个点在右集合 并且交 替出现(这是由二分图性质决定的,因为二分图的左集合或者右 集合内部没有边相连) • 4 整条路径上没有重复的点 • 5 该增广路的起点和终点都是没有被匹配的点 中间的点都是匹配 过的点
• 6 路径上的第奇数条边 都不在原匹配中 而第偶数条边都在匹配中 • 7 当增广路寻找结束并且成功 我们就把奇数条边加入匹配 偶数条 边删除出匹配 最后 匹配数会++
匈牙利算法的具体实现
• 我们可以知道 如果男孩有N个 女孩有M个 那么最后的匹配数 • 一定是<= min(N , M) 的 • 匹配数的现实意义是什么? • 最后能有多少对小伙伴开开心心的去打拳皇98
最小点覆盖
• 在二分图中选择最小的点数 使所有的边都被覆盖 这个点数 就是 最小点覆盖 • 性质 最小点覆盖 = 最大匹配 •证明:最大匹配数为N。 N个点能覆盖所有的边,如果还有边没被覆盖,那么这条边的两 个端点都未匹配,不满足最大匹配,所以不可能存在这种边。 所以N是最小值
最大点独立集
点独立集:选取二分图的一些点组成点集,该点集内的任意两个点都没有边 相连,则称该点集为二分图的点独立集。 最大点独立集:点数最多的点独立集。
Biblioteka Baidu
2
5
3
6
举个例子
• 有ABC DEF六个人 前三个是男生 后三个是女生 • 他们之间的朋友关系是 • A-D A-E B-E B-F C-F • 只有朋友才能一起组个队去打拳皇98 并且每个人都只能和一个朋 友打 • A找到了E B找到了F
• C发现 自己的唯一一个朋友F被拉去了(可以理解为C不能找到一个 还没有小伙伴找他的朋友) • 就去找自己的朋友F问 你被谁拉走了? • F说 是B • 于是C就去找B 问他 你还能再找一个不是F的小伙伴么 我就这一个 女性朋友啊 • B就去找 但是B发现自己如果不去找F的话 就只能去找E了 如果E没 有被拉走就好办了 B就可以直接把F让给C 自己去找E了 • 于是B找到E 问到了那个拉走E的人 : A • 于是B带着十分难受的C去找A 问A是否能像自己一样 看看是否能 换个人打拳皇
什么是二分图
• 在一个图中 把所有的点分成两个部分 • 这两个部分 各自内部的点之间没有边相连
婚姻问题
• 有两个集合 一个集合是男的 一个集合是女的 • 那么婚姻关系就可以被理解为边 • 即 边只存在于两个集合之间
一些基本概念
• 匹配 : 在边的集合M中选出一个子集和E 使E中的每条边都没有公 共端点 则边集E为图的一个匹配 (每个点最多只有一条边与之相 连) • 最大匹配:所有匹配中边最多的匹配 • 完备匹配:若在一个匹配E中,X(Y)中的所有点都有边相连, 则E称为X(Y)的一个完备匹配 • 完美匹配:一个匹配E既为X的完备匹配 也为Y的完备匹配 则称E 为图的完美匹配
匈牙利算法并非二分图匹配系列的全部
• 匈牙利算法可以解决一个已经被构建出来的二分图的最大匹配 • 可是一开始 我们只知道一些条件 甚至 我们都不知道这是一个二 分图 • 很多图论都是这样 我们学习了一把图论算法 • 那图呢?
所以二分图的核心 是建图
• 我们需要把题目给的一些条件 或者题目要求的一些输出 • 通过一些性质 转化成最大匹配等 • 毕竟 • 我们只会求最大匹配啊
奇回路
• 就是 • 这样 •的
偶回路
• 相邻的点颜色是不一样的
如何解决求二分图的最大匹配?
• 1 使用匈牙利算法 • 2 使用HK算法 • 3 使用网络流算法
• 1 是最简单也是复杂度最高的算法 是重点 • 2 作为一个比较难的算法 就不讲了 • 3 是以后会讲的算法
• 所以在这里我们只讲一下匈牙利算法
新行列图变形
•上面是一个 4*4 的方格,方格内的###表示墙,我们要在表格内 没有墙的地方建立碉堡,而且要保证任何两个碉堡之间互相不能 攻击,墙可以阻止大炮的攻击,问最多能建多少个碉堡?
重新拆分
• 重新分配给行列之后 相邻一列中的点 列还是一样的
课后题
• HDU 2444 • HDU 1045 • FZU 2232 • https://vjudge.net/contest/68127
行列匹配法
• 这是一个3*3的矩阵 1代表这个位置有敌人 现在可以一次消灭一 行或者一列的敌人 问最少几次可以消灭完敌人
• 建模方法 • 将行作为左集合 列作为右集合 • 则每个有敌人的点 就是一条边 求最小点覆盖即可
• 有敌人的点(1, 1), (1, 3),(2, 2), (3, 1)。
黑白染色法
• 要求将所有的1改为0 • 每次可以更改一个点 • 或者选相邻的两个点 • 最少需要几次?
• 希望能最少的操作使得所有点被覆盖 • 所以使用最小边覆盖
拆点法
• 拆点法是用于解决最小路径覆盖问题的,给出一个图 • 这个有向图中 我们把每个点分成左右集合中的点 • 1->2这条边 • 就是左集合中的1和右集合中的2连边
• A一看 自己除了E之外 还有一个朋友D • 就去找D • 大家发现 D还没有被拉走 她还在一个人打拳皇人机 • 于是A把队友E换成了D 空下来的E和B组了队 • 过去和B组队的F也空了下来 • C终于找到了队友(女朋友)
• 这条C->F->B->E->A-D的线 • 就是增广路
• 我们可以发现 在其中 第奇数次边 都是没有被确定组队的边 • 即C->F B->E A->D • 都是 • 不存在的!
最后轮到C
C就像刚才说的一样 历经千辛万苦 找到了一条增广路 于是右集合中的EDF纷纷更新了自己被谁拉走 于是C也找到了队友 匹配数+1
如何写成代码?
• 先写一个伪代码看看 • bool vis[N]记录每个女孩是否被问过 不管是在一个男孩的不懈寻 找中被谁询问 如果一个女孩被询问过 她一定会说是谁拉走了她 然后我们去找那个人寻仇 可以知道 多次去找一个人寻仇是没有 意义的 所以 问这个女孩一次就够了 • int linker[N] 记录这个女孩现在的组队状况 • vector<int >q[N] 记录每个男孩的朋友关系