标签:for algo 概念 size cstring ++ mem https 学习
首先二分图匹配的基础概念得清楚:
二分图: 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。
匹配: 两两不含公共端点的边集合M称为匹配(简单的说就是右边的点只能连一条边)
极大匹配: 指在当前已完成的匹配下,无法再通过增加未完成匹配的边的方式来增加匹配的边数
最大匹配: 所有极大匹配当中边数最大的一个匹配
增广路: 若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径.(百度百科)
简单理解就是 假如左边集合A点与右边集合P点 有一条已经匹配的边,而左边集合B点也与右边集合P点 有一条未匹配的边,能不能让A点去匹配右边集合的其他点。从而让B点俘获P点,达到匹配数量增大的情况。 个人理解。。如有错误,欢迎指正。
算法步骤:
1.将集合清空为0.
2.选择一个新的节点寻找增广路
3.重复2操作直到找不出增广路径为止
这里的Flash演示非常不错,简单易懂 https://comzyh.com/blog/archives/148/。
例题:
Usaco-4.2.2 The Perfect Stall
二分图匹配模板题目
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 bool used[1005],cow[233][233]; 6 int fa[1005],tot; 7 int n,m; 8 9 bool find(int x){ 10 for(int i=1;i<=m;i++){ 11 if(!used[i] && cow[x][i]){ 12 used[i]=true; 13 if(!fa[i] || find(fa[i])){ 14 fa[i]=x; 15 return 1; 16 } 17 } 18 } 19 return 0; 20 } 21 22 int main(){ 23 scanf("%d%d",&n,&m); 24 for(int i=1;i<=n;i++){ 25 int x; 26 scanf("%d",&x); 27 for(int j=1;j<=x;j++){ 28 int a; 29 scanf("%d",&a); 30 cow[i][a]=1; 31 } 32 } 33 for(int i=1;i<=n;i++){ 34 memset(used,0,sizeof(used)); 35 if(find(i)) tot++; 36 } 37 printf("%d\n",tot); 38 }
标签:for algo 概念 size cstring ++ mem https 学习
原文地址:http://www.cnblogs.com/OIerLYF/p/7496071.html