什么是二分图

合集下载

二分图及其应用

二分图及其应用
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; }

图论——二分图1:二分图以及判定

图论——二分图1:二分图以及判定

图论——⼆分图1:⼆分图以及判定图,有有向图,⽆向图,稠密图,简单图······算法,有贪⼼法,⼆分法,模拟法,倍增法······那,⼆分图是啥?⼆分法+有向图?于是,我查了许多资料,才对它有⼀定了解。

⼆分图:⼆分图,是图论中的⼀种特殊模型,设G=(V,E)是⼀个⽆向图,如果顶点V可分割为两个互不相交的⼦集(A,B),并且同⼀集合中不同的两点没有边相连。

这就是⼆分图。

举个栗⼦吧:这是不是⼆分图?反正我第⼀次看觉得不是其实,是的,他是⼆分图,尽管看上去是连着的。

若我们将图中的⼀些边转⼀下,变成:这就是⼀个明显的⼆分图。

集合A与B中的点互不相连。

因此,在⼿动判定⼆分图时学会转边!辣魔,⼆分图要⽤计算机判定怎么实现?数竞⼤佬:简单!!!!染⾊⼤法!!!有没有熟悉的感觉0表⽰还未访问,1表⽰在集合A中,2表⽰在集合B中。

col(color)储存颜⾊。

初始化为0.上代码:其实是模板可以记忆。

1 vector <int> v[N];2void dfs(int x,int y){3 col[x]=y;4for (int i=0; i<v[x].size(); i++) {5if (!col[v[x][i]]) dfs(v[x][i],3-y);6if (col[v[x][i]]==col[x]) FLAG=true; //产⽣了冲突7 }8 }9for (i=1; i<=n; i++) col[i]=0; //初始化10for (i=1; i<=n; i++) if (!col[i]) dfs(i,1); //dfs染⾊11if (FLAG) cout<<"NO"; else cout<<"YES";下⼀章我们将讲到⼆分图的匹配,我们明天见。

二分图相关问题

二分图相关问题

X X S X X
X X X X
X代表攻击范围,S代表骑 士
分析
对棋盘染色,设方格的坐标为(x,y),x和y同奇 偶的方格对应X集合,不同奇偶的对应Y集合。 由于骑士沿着“日”字形路线攻击,所以每个 攻击肯定是处于X集合和Y集合之间,而不可 能在两个集合内部。 显然,转化后变为求二分图的最大独立集
匈牙利算法
简要说明:find函数用于判断从k点开始是否能 够找到一条交错路。对于每个可以与k匹配的 顶点j,假如它未被匹配,交错路就已经找到; 假如j已与某顶点x匹配,那么只需调用find(x) 来求证x是否可以与其它顶点匹配,如果返回 true的话,仍可以使j与k匹配;这就是一次 DFS。每次DFS时,要标记访问到的顶点 (cover[j]=true),以防死循环和重复计算。
例题分析
Hanoi Tower Troubles Again! (OIBH Contest)
ZOJ 1239 题目大意:给定柱子数N,按编号从小到大放球, 要求:如果该球不在最底数,则该球和它下面一个 球的编号之和必须为完全平方数。 问对于给定的N,最多能放多少球上去。 N<=50
例题分析
分析
铺放方法
1.2. .333 444. ..2.
Sample Output 4
分析
最小覆盖是覆盖所有的边,因此泥地对应边 建图方式类似于皇家卫士,也是利用行连通块 和列连通块做点,单位泥地对应二分图中的边 要求放最少的板覆盖全部的泥地,转化为求最 小覆盖
二分图最大独立集
图的独立集:寻找一个点集,其中任意两点在 图中无对应边 一般图的最大独立集是NP完全问题 二分图的最大独立集=图的点数-最大匹配数
二分图最小覆盖
图的覆盖:寻找一个点集,使得图中每一条边 至少有一点在该点集中

二分图概念及性质

二分图概念及性质

⼆分图概念及性质 段段续续的看⼆分图已经有些时⽇了。

现在借着周末整理⼀下这么多天对⼆分图的掌握程度。

也好对⼆分图有个整体的认知。

另外,此⽂只针对与⼆分图的⼀些概念和性质,不涉及求最⼤匹配的算法。

好吧,切⼊正题: ⾸先我们抛开⼆分图严谨准确的定义,从⼀个感性的⾓度来认识⼀下什么是⼆分图。

所谓⼆分图,就是能够把图中的定点分成两个X,Y两部分;并且整个图的边只存在于X与Y之间。

就是说,X与Y的内部是不存在边的,否则的话就不是⼆分图了。

举个例⼦:如果把整个⼈类中的男⼈和⼥⼈看成顶点,⼈与⼈之间的恋爱关系(这⾥只讨论异性之间的正常恋爱,同性恋是不被承认的)为边来建⽴图模型的话。

那么这其实就是⼀个⼆分图,其中的男⼈为X部分,⼥⼈为Y部分。

好了,现在我们给出⼆分图严谨的科学定义: 假设图G=(V,E)是⼀个⽆向图,若顶点集 V 可以分解成两个互不相交的⼦集(A,B),并且图中的所有边(i,j)的端点 i,j 分别属于⼦集 A,B 中的元素,则称图 G 是⼀个⼆分图。

为了更好的叙述下⽂,先让我们清楚⼀个概念: 匹配:⽆公共点的边集合。

(形象点就是 X与Y之间的边的个数) 匹配数:边集中边的个数。

最⼤匹配:匹配数最⼤的匹配。

边独⽴集:指图中边集的⼀个⼦集,且该⼦集中的任意两条边之间没有公共点。

(对⽐匹配的概念我们发现,其实边独⽴集和匹配是⼀个概念) 最⼤边独⽴集:包含边数最多的边独⽴集。

(其实就是最⼤匹配,为了⽅便,以后统称最⼤匹配)图1如图1,如果<1,4>是⼀个合法匹配,那么<1,5>就不是⼀个合法的匹配,因为它们有公共点1 。

同样的如果<2,5>是⼀个合法的匹配,那么<2,6>和<3,5>就不是⼀个合法的匹配。

不难看出,其中最⼤匹配是边集:{1, 4, 5},最⼤匹配数为3 。

独⽴集: 是指图的顶点集的⼀个⼦集,且该⼦集中的任意两个顶点之间不存在边。

二分图概念性质(通俗版)

二分图概念性质(通俗版)

二分图的定义二分图的定义非常简单,有两组顶点,一组顶点记为L ,另一组记为R ,L 和R 没有公共的元素,并且所有的边都是连接L 和R 中的点的,对于L 和R 本身,它们内部的任何两个点都没有边相连,这样的无向图就叫二分图。

《组合数学》上这样讲解:二分图可描述为:一,顶点的集合;二,将该顶点集分成两部分的一个划分;三,连接一部分的一个顶点与另一部分的一个顶点的边的集合。

二分图是无向图,那么什么样的无向图是二分图呢?有以下定理:定理:无向图G 为二分图的充分必要条件是,G 至少有两个顶点, 且其所有回路的长度均为偶数。

证明:至少两个顶点,这个显然,把这个条件忽略掉,着重考虑回路长度为偶数这一条件。

先证充分性:由于图中可能有回路也可能无回路,无回路的情况应该最简单,自然考虑分类讨论。

于是,分类讨论后,充分性的证明转化成以下两个命题:a)所有无回路的无向图都是二分图;b)所有有回路且回路长度为偶数的无向图都是二分图。

对于a) ,因为无回路无向图总是能把它画成一棵树,所以,这个命题等价于:所有的树都是二分图。

到这里,命题a) 证明显然,因为有一种很简单的从树构造二分图的方法:令树的奇数层的结点为集合L ,令树的偶数层结点为集合R ,这样就从树得到了一个二分图。

再看命题b) ,可以把b) 转化为a) 。

对于图中的每一个回路,我们都从中拿掉一条边,这样可以消灭所有的回路,由a) 知消灭掉所有回路之后的图是二分图。

把此时得到的二分图画成一棵树,拿掉一条边后的回路此时就是树中的一条路径,并且路径的长度为奇数,这就意味着路径的头结点和尾结点所在层数的编号一个是奇数一个是偶数,用上面的从树构造二分图的方法知,头结点和尾结点分别在集合L 中和集合R 中,我们再把拿掉的这条边加上去,只不过是在L 和R 中的两个顶点间连接了一条边,图仍然是原来的二分图。

至此,充分性得证。

再证必要性。

假设二分图中的一条回路是(v0, v1, v2, …, vm, v0) ,由于是二分图,相邻顶点必不属于同一个集合,用L 标记属于集合L 的点,用R 标记属于集合R 的点,不妨假设v0 属于L ,则上面的回路可以标记为L, R, L, R, …, L, R ,由此可见,回路必有偶数个顶点,因此必有偶数条边。

最大二分图匹配(匈牙利算法)

最大二分图匹配(匈牙利算法)

最大二分图匹配(匈牙利算法)二分图指的是这样一种图:其所有的顶点分成两个集合M和N,其中M或N中任意两个在同一集合中的点都不相连。

二分图匹配是指求出一组边,其中的顶点分别在两个集合中,并且任意两条边都没有相同的顶点,这组边叫做二分图的匹配,而所能得到的最大的边的个数,叫做最大匹配。

计算二分图的算法有网络流算法和匈牙利算法(目前就知道这两种),其中匈牙利算法是比较巧妙的,具体过程如下(转自组合数学):令g=(x,*,y)是一个二分图,其中x={x1,x2...},y={y1,y2,....}.令m为g中的任意匹配。

1。

将x的所有不与m的边关联的顶点表上¥,并称所有的顶点为未扫描的。

转到2。

2。

如果在上一步没有新的标记加到x的顶点上,则停,否则,转33。

当存在x被标记但未被扫描的顶点时,选择一个被标记但未被扫描的x的顶点,比如xi,用(xi)标记y 的所有顶点,这些顶点被不属于m且尚未标记的边连到xi。

现在顶点xi 是被扫描的。

如果不存在被标记但未被扫描的顶点,转4。

4。

如果在步骤3没有新的标记被标记到y的顶点上,则停,否则转5。

5。

当存在y被标记但未被扫描的顶点时。

选择y的一个被标记但未被扫描的顶点,比如yj,用(yj)标记x的顶点,这些顶点被属于m且尚未标记的边连到yj。

现在,顶点yj是被扫描的。

如果不存在被标记但未被扫描的顶点则转道2。

由于每一个顶点最多被标记一次且由于每一个顶点最多被扫描一次,本匹配算法在有限步内终止。

代码实现:bfs过程:#include<stdio.h>#include<string.h>main(){bool map[100][300];inti,i1,i2,num,num1,que[300],cou,stu,match1[100],match2[300],pqu e,p1,now,prev[300],n;scanf("%d",&n);for(i=0;i<n;i++){scanf("%d%d",&cou,&stu);memset(map,0,sizeof(map));for(i1=0;i1<cou;i1++){scanf("%d",&num);for(i2=0;i2<num;i2++){scanf("%d",&num1);map[i1][num1-1]=true;}}num=0;memset(match1,int(-1),sizeof(match1)); memset(match2,int(-1),sizeof(match2)); for(i1=0;i1<cou;i1++){p1=0;pque=0;for(i2=0;i2<stu;i2++){if(map[i1][i2]){prev[i2]=-1;que[pque++]=i2;}elseprev[i2]=-2;}while(p1<pque){now=que[p1];if(match2[now]==-1)break;p1++;for(i2=0;i2<stu;i2++){if(prev[i2]==-2&&map[match2[now]][i2]){prev[i2]=now;que[pque++]=i2;}}}if(p1==pque)continue;while(prev[now]>=0){match1[match2[prev[now]]]=now; match2[now]=match2[prev[now]]; now=prev[now];}match2[now]=i1;match1[i1]=now;num++;}if(num==cou)printf("YES\n");elseprintf("NO\n");}}dfs实现过程:#include<stdio.h>#include<string.h>#define MAX 100bool map[MAX][MAX],searched[MAX]; int prev[MAX],m,n;bool dfs(int data){int i,temp;for(i=0;i<m;i++){if(map[data][i]&&!searched[i]){searched[i]=true;temp=prev[i];prev[i]=data;if(temp==-1||dfs(temp))return true;prev[i]=temp;}}return false;}main(){int num,i,k,temp1,temp2,job;while(scanf("%d",&n)!=EOF&&n!=0) {scanf("%d%d",&m,&k);memset(map,0,sizeof(map));memset(prev,int(-1),sizeof(prev)); memset(searched,0,sizeof(searched));for(i=0;i<k;i++){scanf("%d%d%d",&job,&temp1,&temp2); if(temp1!=0&&temp2!=0)map[temp1][temp2]=true;}num=0;for(i=0;i<n;i++){memset(searched,0,sizeof(searched)); dfs(i);}for(i=0;i<m;i++){if(prev[i]!=-1)num++;}printf("%d\n",num);}}。

二分图的讲解

二分图的讲解
8
例 3个图的匹配数 依次为3, 3, 4.
4
匹配 (续)
设M为G中一个匹配 vi与vj被M匹配: (vi,vj)M v为M饱和点: M中有边与v关联 v为M非饱和点: M中没有边与v关联 M为完美匹配: G的每个顶点都是M饱和点
例 关于M1, a,b,e,d是饱和点 f,c是非饱和点
M1不是完美匹配
(1)
(2)
(3)
6
Hall定理
定理(Hall定理) 设二分图G=<V1,V2,E>中,|V1||V2|. G中存 在从V1到V2的完备匹配当且仅当V1中任意k 个顶点至少与V2 中的k个顶点相邻(k=1,2,…,|V1|). 由Hall定理不难证明, 上一页图(2)没有完备匹配.
定理 设二部图G=<V1,V2,E>中, 如果存在t1, 使得V1中每个 顶点至少关联 t 条边, 而V2中每个顶点至多关联t条边,则G 中存在V1到V2的完备匹配.
注意: n 阶零图为二分图.
2
二分图的判别法
定理 非平凡无向图G=<V,E>是二分图当且仅当G中 无奇数长度的回路
例 下述各图都是二分图
3
匹配
设G=<V,E>, 匹配(边独立集): 任2条边均不相邻的边子集 极大匹配: 添加任一条边后都不再是匹配的匹配 最大匹配: 边数最多的匹配
匹配数: 最大匹配中的边数, 记为1
M2是完美匹配
M1
M2
5
二分图中的匹配
定义 设G=<V1,V2,E>为二部图, |V1||V2|, M是G中最 大匹配, 若V1中顶点全是M饱和点, 则称M为G中V1 到V2的完全匹配. 当|V1|=|V2|时, 完备匹配变成完美 匹配.

二分图最大匹配及常用建图方法

二分图最大匹配及常用建图方法

算法———艺术二分图匹配剖析很多人说,算法是一种艺术。

但是对于初学者的我,对算法认识不是很深刻,但偶尔也能感受到他强大的魅力与活力。

这让我追求算法的脚步不能停止。

下面我通过分析匈牙利算法以及常用建图方式,与大家一起欣赏算法的美。

匈牙利算法匈牙利算法是用来解决最大二分图匹配问题的,所谓二分图即“一组点集可以分为两部分,且每部分内各点互不相连,两部分的点之间可以有边”。

所谓最大二分图匹配即”对于二分图的所有边,寻找一个子集,这个子集满足两个条件,1:任意两条边都不依赖于同一个点。

2:让这个子集里的边在满足条件一的情况下尽量多。

首先可以想到的是,我们可以通过搜索,找出所有的这样的满足上面条件的边集,然后从所有的边集中选出边数最多的那个集合,但是我们可以感觉到这个算法的时间复杂度是边数的指数级函数,因此我们有必要寻找更加高效的方法。

目前比较有效的方法有匈牙利算法和通过添加汇点和源点的网络流算法,对于点的个数都在200 到300 之间的数据,我们是采取匈牙利算法的,因为匈牙利算法实现起来要比网络流简单些。

下面具体说说匈牙利算法:介绍匈牙利之前,先说说“增广轨”。

定义:若P是图G中一条连通两个未匹配顶点的路径,并且属最大匹配边集M的边和不属M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广轨定义总是抽象的下面通过图来理解它。

图中的线段(2->3, 3->1, 1->4)便是上面所说的p路径,我们假定边(1,3)是以匹配的边,(2,3)(1,4)是未匹配的边,则边(4,1)边(1,3)和边(3,2)在路径p上交替的出现啦,那么p就是相对于M的一条增广轨,这样我们就可以用边1,4 和边2,3来替换边1,3 那么以匹配的边集数量就可以加1,。

匈牙利算法就是同过不断的寻找增广轨实现的。

很明显如果二分图的两部分点分别为n 和m,那么最大匹配的数目应该小于等于MIN(n,m); 因此我们可以枚举任第一部分(的二部分也可以)里的每一个点,我们从每个点出发寻找增广轨,最后吧第一部分的点找完以后,就找到了最大匹配的数目,当然我们也可以通过记录找出这些边。

【算法】二分图的判定

【算法】二分图的判定

【算法】⼆分图的判定⼆分图的判定 给定⼀个具有n个顶点的图。

要给图上每个顶点染⾊,并且要使相邻的顶点颜⾊不同。

判断是否能最多⽤两种颜⾊进⾏染⾊。

题⽬保证没有重边和⾃环。

概念:把相邻顶点染成不同颜⾊的问题叫做图的着⾊问题。

对图进⾏染⾊所需要的最⼩颜⾊数称为最⼩着⾊度。

最⼩着⾊度为2的图称作⼆分图。

分析:如果只⽤两种颜⾊,那么确定⼀个顶点的颜⾊之后,和它相邻的顶点的颜⾊也就确定了。

因此,选择任意⼀个顶点出发,依次确定相邻顶点的颜⾊,就可以判断是否可以被2种颜⾊染⾊了。

这个问题⽤深度优先搜索可以简单实现。

#include <bits\stdc++.h>using namespace std;#define MAX_V 1000//输⼊vector<int> G[MAX_V]; //图int V; //顶点数int color[MAX_V]; //顶点的颜⾊(1 or -1)//顶点v,颜⾊cbool dfs(int v,int c){color[v] = c;//把当前顶点相邻的顶点扫⼀遍for(int i = 0;i < G[v].size(); i++){//如果相邻顶点已经被染成同⾊了,说明不是⼆分图if(color[G[v][i]] == c) return false;//如果相邻顶点没有被染⾊,染成-c,看相邻顶点是否满⾜要求if(color[G[v][i]] == 0 && !dfs(G[v][i],-c)) return false;}//如果都没问题,说明当前顶点能访问到的顶点可以形成⼆分图return true;}void solve(){//可能是不连通图,所以每个顶点都要dfs⼀次for(int i = 0;i < V; i++){if(color[i] == 0){//第⼀个点颜⾊为 1if(!dfs(i,1)){cout << "No" << endl;return;}}}}int main(){//输⼊}。

图的匹配

图的匹配
图表 2 匈牙利算法
理解了这个算法,就不难写出人员分配问题的解答了。在给出程序之前,先做一些假 设:
为了简单起见,假设工人数等于工作数,即 N=M,且 N≤100,这里,N 也可以看作 是二分图的|X|和|Y|。
数据从文件input.txt中读入,首先是N和|E|,下面|E|行每行两个数(I, J),表示工人I可以 胜任工作J,即二分图中的边xiyj。
for j := 1 to n do if map[i, j] > lx[i] then lx[i] := map[i, j];
for k := 1 to n do repeat fillchar(x, sizeof(x), 0); fillchar(y, sizeof(y), 0); if find(k) then break; d := maxint; for i := 1 to n do if x[i] then for j := 1 to n do if not y[j] then if lx[i] + ly[j] - map[i, j] < d then d := lx[i] + ly[j] - map[i, j]; for i := 1 to n do if x[i] then lx[i] := lx[i] - d; for i := 1 to n do if y[i] then ly[i] := ly[i] + d; until false;
一条连接两个不同的 M 非饱和点的 M 交错链称为 M 增广链。 两个集合S1与S2的“异或”操作S1⊕S2是指集合S1⊕S2=(S1∩S2)\(S1∪S2) 容易看出,设 M 是 G 的匹配,P 是 G 中的 M 增广链、则 M⊕P 也是 G 的匹配,而且

二分图

二分图

二分图又称双分图、二部图,指顶点可以分成两个不相交的集使得在同一个集内的顶点不相邻(没有共同边)的图。

特性∙最小边覆盖集的基数等于最大独立集的基数∙最大独立集的基数与最大匹配的基数之和,等于顶点数目∙连通的二部图:o最小顶点覆盖集的基数等于最大匹配的基数图为二分图当且仅当……∙没有奇数圈∙点色数为2问题简介设G=(V,E)是一个无向图。

如顶点集V可分区为两个互不相交的子集V1,V2之并,并且图中每条边依附的两个顶点都分属于这两个不同的子集。

则称图G为二分图。

二分图也可记为G=(V1,V2,E)。

给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。

选择这样的子集中边数最大的子集称为图的最大匹配问题(maximal matching problem)如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备,完美匹配。

算法描述求最大匹配的一种显而易见的算法是:先找出全部匹配,然后保留匹配数最多的。

但是这个算法的时间复杂度为边数的指数级函数。

因此,需要寻求一种更加高效的算法。

下面介绍用增广路求最大匹配的方法(称作匈牙利算法,匈牙利数学家Edmonds于1965年提出)。

增广路的定义(也称增广轨或交错轨):若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。

由增广路的定义可以推出下述三个结论:1-P的路径长度必定为奇数,第一条边和最后一条边都不属于M。

2-将M和P进行异或操作(去同存异)可以得到一个更大的匹配M’。

3-M为G的最大匹配当且仅当不存在M的增广路径。

算法轮廓:(1)置M为空(2)找出一条增广路径P,通过异或操作获得更大的匹配M’代替M(3)重复(2)操作直到找不出增广路径为止时间空间复杂度时间复杂度邻接矩阵:最坏为O(n^3) 邻接表:O(mn) 空间复杂度邻接矩阵:O(n^2) 邻接表:O(m+n)样例程序Program Hungary;CosntMax=100;VarData:Array[1..Max,1..Max] of Boolean;Result:Array[1..Max] of Longint;State:Array[1..Max] of Boolean;M,N1,N2,I,T1,T2,Ans:Longint;Function Dfs(P:Longint):Boolean;VarI:Longint;BeginFor I:=1 to N2 doIf Data[P,I] and Not(State[I]) Then BeginState[I]:=True;If (Result[I]=0) or Dfs(Result[I]) Then BeginResult[I]:=P;Exit(True);End;End;Exit(False);End;BeginReadln(N1,N2,M);Fillchar(Data,Sizeof(Data),False);For I:=1 to M do BeginReadln(T1,T2);Data[T1,T2]:=True;End;Fillchar(Result,Sizeof(Result),0);Ans:=0;For I:=1 to N1 do BeginFillchar(State,Sizeof(State),0);If Dfs(I) Then Inc(Ans);End;Writeln(Ans);End.。

二分图

二分图

二分图二分图又称作二部图,是图论中的一种特殊模型。

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

1定义简而言之,就是顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集。

2辨析示例区别二分图,关键是看点集是否能分成两个独立的点集。

上图中U和V构造的点集所形成的循环圈不为奇数,所以是二分图。

上图中U和V和W构造的点集所形成的的循环圈为奇数,所以不是二分图。

3必要条件无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数。

证先证必要性。

设G为二分图<X,E,Y>。

由于X,Y非空,故G至少有两个顶点。

若C为G 中任一回路,令C=(v0,v1,v2,…,v l-1,v l=v0)其中诸vi(i=0,1,…,l)必定相间出现于X及Y中,不妨设{v0,v2,v4,…,v l=v0}&Iacute;X{v1,v3,v5,…,v l-1}&Iacute;Y因此l必为偶数,从而C中有偶数条边。

再证充分性。

设G的所有回路具有偶数长度,并设G为连通图(不失一般性,若G不连通,则可对G的各连通分支作下述讨论)。

令G的顶点集为V,边集为E,现构作X,Y,使<X,E,Y>=G。

取v0&Icirc;V,置X={v|v=v0或v到v0有偶数长度的通路}Y=V-XX显然非空。

现需证Y非空,且没有任何边的两个端点都在X中或都在Y中。

由于|V|≥2并且G为一连通图,因此v0必定有相邻顶点,设为v1,那么v1&Icirc;Y;故Y不空。

设有边(u,v),使u&Icirc;X,v&Icirc;X。

那么,v0到u有偶数长度的通路,或u=v0;v0到v有偶数长度的通路,或v=v0。

二 分 图

二  分  图
n时,完全二分图G记为Km,n。
. 二分图
1.1 二分图的基本概念
✓定理
无向图G为二分图的充分必要条件是, G至少有两个顶点,且其所有回路的长度均 为偶数。
. 二分图
1.2 二分图的基本概念
➢定义9.2
设G = <X,E,Y>为二分图,ME。称M为G
的一个匹配(matching),如果M中任何两条边都没 有公共端点。G的所有匹配中边数最多的匹配称为最 大匹配(maximal matching)。如果X(Y)中任一顶 点均为匹配M中边的端点,那么称M为X(Y)-完全匹 配(perfect matching)。若M既是X-完全匹配又是Y-完 全匹配,则称M为G的完全匹配。
离散数学导论
. 二分图
1.1 二分图的基本概念
➢定义
无向图G = <V,E,>称为二分图(bipartite
graph),如果有非空集合X,Y使X∪Y = V, X∩Y = ,且对每一eE,(e) = (x, y),xX,yY。 此时常用<X,E,Y>表示二分图G。若对X中任一x及Y
中任一y恰有一边eE,使(e) = (x, y), 则称G为完全 二分图(complete bipartite graph)。当X = m,Y =
. 二 分图
1.2 二分图的基本概念
➢定义9.3
设G = <X,E,Y>,M为G的一个匹配。
(1)M中边的端点称为M-顶点,其它顶点称为非
M-顶点。
(2)G中vk到vl的通路P称为交替链,如果P的起
点vk和终点vl为非M-顶点,而其边的序列中非匹配 边与匹配边交替出现(从而首尾两边必为非匹配边, 除顶点vk,vl以外各顶点均为M-顶点)。特别地, 当一边(v, v‘)两端点均为非M-顶点,通路(v, v')

基于二分图匹配的任务分配算法

基于二分图匹配的任务分配算法

基于二分图匹配的任务分配算法在现代的科技发展中,任务分配算法是一个非常重要的领域。

它可以帮助我们在许多领域中提高效率和减少成本。

其中,在商业领域、工业领域和科学领域等方面,任务分配算法都有着极其广泛的应用。

而基于二分图匹配的任务分配算法是其中一种比较常见的方法。

首先,什么是二分图?简单来说,二分图就是一种特殊的图形结构。

在二分图中,所有的结点被分为两个部分,而两个部分之间的边只存在于不同的部分之间。

此外,在一张二分图中,不存在连向同一部分中的两个结点的边。

在二分图中进行任务分配的基本思路就是将任务和执行者分别作为两个部分的结点,并且需要保证任务和执行者之间一一对应。

也就是说,一个执行者只能处理一个任务,而一个任务也只能指定一个执行者进行处理。

这样一来,任务和执行者之间的匹配就可以通过二分图进行处理。

二分图匹配的常用算法有很多,而其中比较常见的算法是匈牙利算法。

匈牙利算法的基本思路是通过不断寻找增广路的方法来不断扩展前一个匹配的结果。

在匈牙利算法中,每个执行者都会依次尝试处理任务,如果任务还没有被其他执行者处理,并且执行者有能力处理该任务,那么该任务就会被分配给该执行者。

如果任务已经被其他执行者分配了,那么该执行者就会尝试寻找其他任务,直到找到自己可以处理的任务为止。

如果该执行者无法找到自己可以处理的任务,那么他就会放弃这一轮任务分配。

通过这种方式,匈牙利算法能够保证任务和执行者之间始终保持一一对应关系,从而实现高效的任务分配。

除了匈牙利算法,基于二分图匹配的任务分配算法还有很多其他的方法。

例如,可以通过网络流算法来解决二分图匹配问题。

在网络流算法中,二分图中的每个结点都被视为一个顶点,并且每个顶点之间的边都被赋予一个流量值。

通过不断调整流量值,网络流算法可以找到最优的任务分配方案。

此外,还可以使用线性规划算法、遗传算法等其他算法来解决二分图匹配问题。

不同的算法有不同的优点和适用范围,具体选择哪种算法需要根据具体的应用场景来决定。

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

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

⼆分图最⼤匹配:匈⽛利算法的python实现⼆分图匹配是很常见的算法问题,⼀般⽤匈⽛利算法解决⼆分图最⼤匹配问题,但是⽬前⽹上绝⼤多数都是C/C++实现版本,没有python版本,于是就⽤python实现了⼀下深度优先的匈⽛利算法,本⽂使⽤的是递归的⽅式以便于理解,然⽽迭代的⽅式会更好,各位可以⾃⾏实现。

1、⼆分图、最⼤匹配什么是⼆分图:⼆分图⼜称作⼆部图,是图论中的⼀种特殊模型。

设G=(V,E)是⼀个⽆向图,如果顶点V可分割为两个互不相交的⼦集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为⼀个⼆分图。

什么是匹配:把上图想象成3位⼯⼈和4种⼯作,连线代表⼯⼈愿意从事某项⼯作,但最终1个⼯⼈只能做⼀种⼯作,最终的配对结果连线就是⼀个匹配。

匹配可以是空。

什么是最⼤匹配:在愿意从事的基础上,能够最多配成⼏对。

现在要⽤匈⽛利算法找出最多能发展⼏对。

[color=green][size=medium]匈⽛利算法是解决寻找⼆分图最⼤匹配的。

更多⼆分图最⼤匹配的图解可以参考 /5576502/1297344以下是代码,为了图省事使⽤了类,实际上并不需要这样M=[]class DFS_hungary():def__init__(self, nx, ny, edge, cx, cy, visited):self.nx, self.ny=nx, nyself.edge = edgeself.cx, self.cy=cx,cyself.visited=visiteddef max_match(self):res=0for i in self.nx:if self.cx[i]==-1:for key in self.ny: # 将visited置0表⽰未访问过self.visited[key]=0res+=self.path(i)return resdef path(self, u):for v in self.ny:if self.edge[u][v] and (not self.visited[v]):self.visited[v]=1if self.cy[v]==-1:self.cx[u] = vself.cy[v] = uM.append((u,v))return 1else:M.remove((self.cy[v], v))if self.path(self.cy[v]):self.cx[u] = vself.cy[v] = uM.append((u, v))return 1return 0ok,接着测试⼀下:if__name__ == '__main__':nx, ny = ['A', 'B', 'C', 'D'], ['E', 'F', 'G', 'H']edge = {'A':{'E': 1, 'F': 0, 'G': 1, 'H':0}, 'B':{'E': 0, 'F': 1, 'G': 0, 'H':1}, 'C':{'E': 1, 'F': 0, 'G': 0, 'H':1}, 'D':{'E': 0, 'F': 0, 'G': 1, 'H':0}} # 1 表⽰可以匹配, 0 表⽰不能匹配cx, cy = {'A':-1,'B':-1,'C':-1,'D':-1}, {'E':-1,'F':-1,'G':-1,'H':-1}visited = {'E': 0, 'F': 0, 'G': 0,'H':0}print DFS_hungary(nx, ny, edge, cx, cy, visited).max_match()结果为4,是正确的。

图论——染色法判定二分图

图论——染色法判定二分图

图论——染⾊法判定⼆分图 ⾸先明确概念: ⼆分图:设G=(V,E)是⼀个⽆向图,如果顶点V可分割为两个互不相交的⼦集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为⼀个⼆分图。

奇数环:⼀个图中边数为奇数的环。

染⾊法原理: ⾸先任意取出⼀个顶点进⾏染⾊,和该节点相邻的点有三种情况: 1.如果未染⾊,那么继续染⾊此节点(染为另⼀种颜⾊) 2.如果已染⾊但和当前节点颜⾊不同,则跳过该点 3.如果已染⾊并且和当前节点颜⾊相同,返回失败(该图不是⼆分图) 明确⼆分图、奇数环、染⾊法之间的关系: 如果⼀个图中存在奇数环,那么这个图⼀定不是⼆分图;这⼀点显然成⽴。

如果⼀个图中不存在奇数环,那么这个图⼀定是⼆分图: 证明:⽤染⾊法。

从某个点开始逐层交叉染⾊,在染⾊过程中: 若发现有某条边的两个端点着⾊相同,则必定存在奇数环①,与题意相⽭盾。

若没有发现,则根据染⾊法原理,每⼀条边的两端着⾊必然不同,那么根据⼆分图的定义,就可知这个图是⼀个⼆分图。

①的证明: 不妨设这条边的两个端点着⾊都为1,且这两点必然是由同⼀个源点扩展⽽来。

那么根据染⾊法原理,因为这两个点的着⾊相同,那么从源点到这两个点所经过的边数(假设分别为x和y)的奇偶性必然相同,那么这个环的总边数为x+y+1,由数学知识得这个数必然是奇数。

  证毕! 模板题链接: 代码如下:#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>using namespace std;const int N = 100010, M = 200010;struct Edge{int to,next;}edge[M];int cnt;int n,m;int h[N],color[N];void add_edge(int u,int v){edge[++cnt].to=v;edge[cnt].next=h[u];h[u]=cnt;}bool dfs(int u,int c){color[u]=c;for(int i=h[u]; ~ i;i=edge[i].next){int to=edge[i].to;if(color[to]==c){return false;}else if(!color[to]&&!dfs(to,3-c))return false; }return true;}int main(){scanf("%d%d",&n,&m);memset(h,-1,sizeof h);for(int i=1;i<=m;i++){int a,b;scanf("%d%d",&a,&b);add_edge(a,b);add_edge(b,a);}bool flag=true;for(int i=1;i<=n;i++){if(!color[i]){if(!dfs(i,1)){flag=false;break;}}}if(flag)printf("Yes\n");else printf("No\n");}。

二分图及匹配算法

二分图及匹配算法

Chapter 3
二分图最佳匹配
-二分图最佳匹配-
定义:图G中权值和最大的完全匹配。
Kuhn-Munkras算法:该算法是通过给每个顶点一个标号(叫做顶标) 来把求最大权匹配的问题转化为求完备匹配的问题的。设顶点Xi的顶标 为A[ i ],顶点Yj的顶标为B[ j ],顶点Xi与Yj之间的边权为w[i,j]。在算法 执行过程中的任一时刻,对于任一条边(i,j),A[ i ]+B[j]>=w[i,j]始终成立。 KM算法的正确性基于以下定理: 若由二分图中所有满足A[ i ]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等 子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。 KM算法流程: (1)初始化可行顶标的值; (2)用匈牙利算法寻找完备匹配; 这样做是O(n^4)的
-稳定婚姻问题-
Байду номын сангаас
求婚拒绝算法(Gale-Shapley算法/延迟认可算法): 先对所有男生进行单身标记,称其为单身狗男。当存在单身狗男时,进行 以下操作:
①选择一位单身狗男在所有尚未拒绝她的女生中选择一位被他排名最优先 的女神;
②女神将正在追求她的单身狗男与其现任进行比较,选择其中排名优先的 男生作为其男友,即若单身狗男优于现任,则现任被抛弃为前任;否则保 留其男友,拒绝单身狗男。 ③若某男生被其女友抛弃,则重新变成单身狗男,至①重复。
Chapter 5
稳定婚姻问题
-稳定婚姻问题-
你们班上有n位男生和n位女生,每个人对异性都有一个排序,表示对他们 的爱恋程度。现在你的任务是使他们凑成CP,使他们的爱情坚不可摧! 满足一下条件的爱情不是坚不可摧的: 男生u和女生v不是CP,但他们爱恋对方的程度都大于爱恋现任 的程度。 因为这样男生u和女生v会抛下已经是CP的那个她/他,另外组成一对。于 是乎多出了两位前任,这样就会让人再也无法相信爱情了! 怎么能避免悲剧的发生呢?

ACM讲课之二分图匹配(匈牙利算法)ppt课件

ACM讲课之二分图匹配(匈牙利算法)ppt课件

1
1
1
2
2
3
323Fra bibliotek44
5
可编辑课件PPT
5
11
i = 3时: Pre[1] = 3;
1 2 3 4 5
可编辑课件PPT
1 1
2
3
4
5
12
i = 4时 : Pre[3] = 2; Pre[2] = 1; Pre[5] = 3; Pre[1] = 4;
1 2 3 4 5
可编辑课件PPT
1 2 3 4
匹配1
v1
v2
v3
匹配2
v1
v2
v3
v4
v5
v4
v5
可编辑课件PPT
3
二分图的最大匹配
最大匹配:图中包含边数最多的匹配称为图的最大匹配。
今天我要讲的是无权二分图的最 大匹配问题,采用匈牙利算法。
可编辑课件PPT
4
匈牙利算法必备知识:
1.盖点:有被M中的边关联到的节点,未盖点则相反。
2.增广路径:若二分图中有一条路径p,其起始点和结束点都是未盖 点,其间属于M的边和不属于M的边交替出现,则称路径p是一条关于 M的增广路径。
5
13
二分图最大匹配延伸
最小点覆盖 最小边覆盖 最大独立集 有向图最小路径覆盖 最优匹配(KM算法)
可编辑课件PPT
14
此课件下载可自行编辑修改,此课件供参考! 部分内容来源于网络,如有侵权请与我联系删除!感谢你的观看!
匈牙利算法: 计算二分图最大匹配就是应用增广路径的概念,每次寻找一条关于M 的增广路径p,通过M和增广路径进行异或,使得M中的匹配数增加1 。以此类推,直至二分图中不存在关于M的增广路径为止。此时得到 匹配M就是图G的一个最大匹配。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
匹配有很多种。
我们定义匹配点、匹配边、未匹配点、未匹配边,它们的含 义非常显然。例如图3中1,4,5,7为匹配点,其他顶点为未匹 点;1-5、4-7为匹配边,其他边为非匹配边。
最大匹配&完美匹配
最大匹配:一个图所有的匹配中,所匹配的边数最多 的匹配,称为这个图的最大匹配。图4是一个最大匹 配。 完美匹配:如果一个图的某个匹配中,所有的顶点都 是匹配点,那么它就是一个完美匹配。图 4 是一个完 美匹配。显然,完美匹配一定是最大匹配(完美匹配 的任何一个点都已经匹配,添加一条新的匹配边一定 会与已有的匹配边冲突)。但并非每个图都存在完美 匹配。
交替路:图的一条简单路径,满足任意相邻的两条边, 一条在匹配内,一条不在匹配内 。
增广路:从一个未匹配点出发,走交替路, 如果途径另一个未匹配点(出发的点不算), 则这条交替路称为增广路(agumenting path)。 例如,图 5 中的一条增广路如图 6 所示 (图中的匹配点均用红色标出)
/*==================================================*\ | 二分图匹配(匈牙利算法BFS 实现) | INIT: g[][]邻接矩阵; | CALL: res = MaxMatch (); Nx, Ny 初始化!!! | 优点:适用于稀疏二分图,边较少,增广路较短。 | 匈牙利算法的理论复杂度是O(VE) \*==================================================*/ const int MAXN = 1000; int g[MAXN][MAXN], Mx[MAXN], My[MAXN], Nx, Ny; int chk[MAXN], Q[MAXN], prev[MAXN]; int MaxMatch(void) { int res = 0; int qs, qe; memset(Mx, -1, sizeof(Mx)); memset(My, -1, sizeof(My)); memset(chk, -1, sizeof(chk)); for (int i = 0; i < Nx; i++) { if (Mx[i] == -1) {//对于x集合中的每个没有匹配的点i进行一次bfs找 交错轨 qs = qe = 0; Q[qe++] = i; prev[i] = -1; bool flag = 0;//判断是否找到
下面给出此算法的一个例子

(1)置M = 空,对x1-x6标记(*)。
(2)找到交替链(x1, y1)(由标记(x1),(*)回溯得),置M = {(x1, y1)}。
(3)找到交替链(x2, y2)(由标记(x2),(*)回溯得),置M = {(x1, y1), (x2, y2)}。
(4)找到交替链(x3, y1, x1, y4)(图中虚线表示非匹配边, 细实线表示交替链中非匹配边,粗实线表示匹配边),因而得 M = {(x2, y2), (x3, y1),(x1, y4)}。
增广路的重要特点:
1. 有奇数条边 ; 2. 起点在二分图的X边,终点在二分图的Y边 ; 3. 路径上的点一定是一个在X边,一个在Y边,交错出现; 4. 整条路径上没有重复的点 ; 5. 起点和终点都是目前还没有配对的点,其他的点都已经出现在匹配 子图中 ;
6. 路径上的所有第奇数条边都是目前还没有进入目前的匹配子图的 边
,而所有第偶数条边都已经进入目前的匹配子图。奇数边比偶数边多一 条边 ;
7. 于是当我们把所有第奇数条边都加到匹配子图并把条偶数条边都删
除,匹配数增加了1。
我们可以通过不停地找增广路来增加匹配中的匹配边和
匹配点。找不到增广路时,达到最大匹配(这是增广路定理
)。匈牙利算法正是这么做的。
匈牙利算法主要思想
则用(yi)去标记X中结点x。
(2),(3)交替执行,直到下述情况之一出现为止 : (I)标记到一个Y中顶点y,它不是M顶点。这 时从y出发循标记回溯,直到(*)标记的X中 顶点x,我们求得一条增广路。设其长度为 2k+1,显然其中k条是匹配边,k+1条是非匹 配边。 (II)步骤(2)或(3)找不到可标记结点,而又不 是情况(I)。
(5)找到交替链(x4, y3)(由标记(x4),(*)回溯得), M = {(x2, y2), (x3, y1),(x1, y4), (x4, y3)}。
(6)找到交替链(x5, y4, x1, y1, x3, y7)因而得 M = {(x2, y2), (x4, y3),(x5, y4), (x1, y1), (x3, y 7)}
即: 初始化匹配子图为空 While 找得到增广路径 Do 把增广路径添加到匹配子图中
匈牙利算法步聚:
(1) 首先用(*)标记X中所有的非M顶点,然后 交替进行步骤(2),(3)。
(2) 选取一个刚标记(用(*)或在步骤(3)中用 (yi)标记)过的X中顶点,例如顶点xi,如 果xi与y为同一非匹配边的两端点,且在本 步骤中y尚未被标记过,则用(xi)去标记Y 中顶点y。重复步骤,直至寻找到Y或者或 者访问完所有与xi相关点。 (3) 选取一个刚标记(在步骤(2)中用(xi)标记) 过的Y中结点,例如yi,如果yi与x为同一匹 配边的两端点,且在本步骤中x尚未被标记过,
二分图及其应用
(Bipartite Graph & Applications)
主要内容:
什么是二分图? 二分图的各种匹配的定义?
如何利用匈牙利算法求最大匹配?
二分图的最小顶点覆盖 DAG图的最小路径覆盖 二分图的最大独立集
什么是二分图?
二分图又称作二部图,是图论中的一种特殊模型。 设 G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的 子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i 和j分别属于这两个不同的顶点集(i in A,j in B),则称图G 为一个二分图。
(4)当(2),(3)步骤中断于情况(I),则将增广 路中非匹配边改为匹配边,原匹配边改为 非匹配边(从而得到一个比原匹配多一条边 的新匹配),回到步骤(1),同时消除一切 现有标记。 (5)对一切可能,(2)和(3)步骤均中断于情况 (II),或步骤(1)无可标记结点,算法终止(算法 找不到交替链).
算法: 从二分图中找出一条路径来, 让路径的起点和终点都是还没有匹 配过的点,并且路径经过的连线是 一条没被匹配、一条已经匹配过交 替出现。 找到这样的路径后,显然路径 里没被匹配的连线比已经匹配了的 连线多一条,于是修改匹配图,把 路径里所有匹配过的连线去掉匹配 关系,把没有匹配的连线变成匹配 的,这样匹配数就比原来多1个。 不断执行上述操作,直到找不 到这样的路径为止。
A
B
什么是二分图?
二分图的一个等价定义:不含有(含奇数条边
的环)的图。图1是一个二分图。为了清晰,我们都 把它画成图2的形式。 无向图G为二分图的充分必要条件是,G至少有 两个顶点,且其所有回路的长度均为偶数
匹配
在图论中一个匹配是一个边的集合,其中任意 两条边都没有公共顶点。例如,图3中红色的边。
相关文档
最新文档