当前位置:文档之家› 二分图及其应用

二分图及其应用

14
求最大匹配举例
①取一个初始匹配M={Bb,Cc,Dd}. ②用标记法从点A开始求得一条增广路:=(AcCe)(左图). ③用调整匹配M:将中属于M的边删去并将其中不属于M的
其它边添加到M中得到比M多一边的新匹配M’(如右图 示). ④因对M’用标记法只能从E或F开始,但都不能求出M’的 任何增广路,故判定M’是一个最大匹配.
13
匈牙利算法:
初始时最大匹配为空 for 二分图左半边的每个点i do 从点i出发寻找增广路径。如果找到,则把它取反
(即增加了总了匹配数)
如果二分图的左半边一共有n个点,那么最多找n 条增广路径。如果图中共有m条边,那么每找一 条增广路径(DFS或BFS)时最多把所有边遍历一 遍,所花时间也就是m。所以总的时间大概就是O (n * m)。
6
例2:工作分配问题
问题 某教研室有4位教师:A,B,C,D. A能教课程5;B能教 1,2;C能教1,4;D能教课程3.能否适当分配他们的任务,使4 位教师担任4门不同课并且不发生安排教师教他不能教的 课的情况?
此问题可归结为二分图的数学模型: G={A,B,C,D},E,{1,2,3,4,5},(X,y)E,如果X能教y.一 个满足要求的工作分配正是一个含有4条边的一个最大匹 配.
for(i=0;i<n;i++) { if(mark1[i]) { if(!v[i].empty()){ memset(mark2,true,sizeof(mark2)); for(j=0;j<v[i].size();j++) { point = v[i][j]; if(!mark2[point]) continue; mark2[point] = false; if(list[point] == -1 || dfs(point)) { list[point] = i; num++; break; } } } mark1[i] = false; } } if(flog || list[0] != -1) cout << num-1 << endl; else cout << num << endl; } int main() { int i,j,s,d; while(cin>>n) { if(n == 0)break; v.clear(); v.resize(n); cin >> m >> edge; for(i=0;i<edge;i++) { cin >> j >> s >> d; v[s].push_back(d); } Solve(); } return 0; }
第13讲 二分图及其应用 (Bipartite Graph &
Applications)
1
主要内容
什么是二分图 二分图的最大匹配 匈牙利算法 二分图的最小顶点覆盖 DAG图的最小路径覆盖 二分图的最大独立集
2
什么是二分图?
如果一个图的顶点可以分为两个集合X和 Y,图的所有边一定是有一个顶点属于集 合X,另一个顶点属于集合Y,则称该图 为“二分图”(Bipartite Graph)
A(*) B C(c) D E F
A(c) B C D(d) E(*) F (*)
M’
a b c(A) d e(C) f
a b c(D)d
ef
(E) 15
/*hdoj_1150匈牙利算法 */ #include<iostream> #include<string> #include<vector> using namespace std; bool mark1[100],mark2[100]; int list[100]; int n,m,edge,num; vector<vector<int> > v; bool dfs(int to) { register int i,point,s = list[to]; for(i=0;i<v[s].size();i++) { point = v[s][i]; if(!mark2[point]) continue; mark2[point] = false; if(list[point]==-1 || dfs(point)){ list[point] = s; return true; } } return false; } void Solve() { int i,j,point; bool flog = false; memset(mark1,true,sizeof(mark1)); memset(list,-1,sizeof(list)); num=0; for(i=0;i<n;i++) { for(j=0;j<v[i].size();j++) if(list[v[i][j]] == -1) { mark1[i] = false; list[v[i][j]] = i; num++; if(i==0) flog = true; break; } }
10
图示:
男1 男2
女1 女2 女3
11
增广路的定义(也称增广轨或交错轨): 若P是图G中一条连通两个未匹配顶点的路径,并且属M的边 和不属M的边(即已匹配和待匹配的边)在P上交替出现,则 称P为相对于M的一条增广路径。由增广路的定义可以推出 下述三个结论:
1. P的路径长度必定为奇数,第一条边和最后一条边都不属于
M。
2. P经过取反操作可以得到一个更大的匹配M’。 3. M为G的最大匹配当且仅当不存在相对于M的增广路径。
12
图1
图2
图1是给出的二分图中的一个匹配:[1,5]和[2,6]。图2就是在这个 匹配的基础上找到的一条增广路径:3->6->2->5->1->4。
在最初始时,还没有任何匹配时,图1中的两条灰色的边本身也是增广路径。 因此在这张二分图中寻找最大配匹的过程可能如下: (1)找到增广路径1->5,把它取反,则匹配数增加到1。 (2)找到增广路径2->6,把它取反,则匹配数增加到2。 (3)找到增广路径3->6->2->5->1->4,把它取反,则匹配数增加到3。 (4)再也找不到增广路径,结束。
3
二分图举例
4
例1:婚配问题


5
二分图的匹配与最大匹配
定义: 二分图 G=X,E,Y 的边集E的子集M称为G的一个匹配, 如果M的任二边都没有公共端点; G中边数最多的匹配称为最大 匹配(不唯一);含有G的每一点的匹配称为完美匹配(必为最大 匹配仍不唯一).
下面是最大,完美匹配的例子(用粗线表示):
A
B
C
D
1
2
3
45
7
如何求二分图 的最大匹配呢?
8
经典算法:
匈牙利算法
9
匈牙利算法(求二分图最大匹配)
谈匈牙利算法自然避不开Hall定理
Hall定理:对于二分图G,存在一个匹配M, 使得X的所有顶点关于M饱和的充要条件是: 对于X的任意一个子集A,和A邻接的点集为 T(A),恒有: |T(A)|>= |A|
相关主题