二分图:二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。
最大匹配:
给定一个二分图G,M为G边集的一个子集,如果M满足当中的任意两条边都不依附于同一个顶点,则称M是一个匹配。图中包含边数最多的匹配称为图的最大匹配。
最小覆盖点:
无向图中,最少需要多少个点可以覆盖所有的边。一条边被覆盖是指至少有一个和它相邻的点被选中。
特别的,如果该图是二分图,有 最小点覆盖=最大二分匹配。
算法:
匈牙利算法. 不断在图中寻找增广路,增广路即路上的边为非匹配边,匹配边,非匹配边,。。。。 然后将匹配边和非匹配边互换可使得匹配边增加, 当找不到增广路时,此时为最大匹配边
http://blog.csdn.net/hackbuteer1/article/details/7398008 这里讲的比较详细
例题: hdu 2063 过山车
明显裸的二分图最大匹配边
代码:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int map[555][555];//图的表示 int visit[555];//记录改点在这一次寻找增广路中是否已被利用 int match[555];//表示该条匹配边集合N是和集合M的哪个点连接,找到增广路将匹配与非匹边置换时需要 int hash[555];//记录改点是否在图中 int n,m; int dfs(int u) { for(int i= 1; i<= m; i++) if(map[u][i] && !visit[i]) { visit[i]= 1; if(!match[i] || dfs(match[i]))// 找到增广路的条件:!match[i]表示当前只有1条边且为非匹配边, { //dfs(match[i]) 表示找到 非匹配边,匹配边,非匹配边。。此类的情况 match[i]= u;// 这里相当把匹配边与非匹配边互换 return 1; } } return 0; } int main() { int t; while(scanf("%d",&t)!=EOF && t) { memset(map, 0, sizeof(map)); memset(match, 0, sizeof(match)); memset(hash, 0, sizeof(hash)); scanf("%d %d",&n,&m); int a,b; int sum= 0; for(int i= 1; i<= t; i++) { scanf("%d %d",&a,&b); if(!hash[a]) { sum++; hash[a]= 1; } map[a][b]= 1; } int ans= 0; for(int i= 1; i<= n; i++) { memset(visit, 0 ,sizeof(visit)); if(dfs(i)) ans++; } printf("%d\n",ans); } return 0; }
hdu 2119 Matrix
输入的矩阵可看成一个二分图, map[x][y]= 1表示 集合X中的点1 和集合Y中的点1相连, 最后求最小覆盖点即可
PS: 在二分图中为何最小覆盖点== 最大匹配边 某渣还没搞懂。。。。
代码:
#include<stdio.h> #include<string.h> int map[111][111]; int visit[111]; int match[111]; int m,n; int dfs(int u) { for(int i= 1; i<= m; i++) if(map[u][i] && !visit[i]) { visit[i]= 1; if(!match[i] || dfs(match[i])) { match[i]= u; //找到增广路,匹配边与非匹配边互换 return 1; } } return 0; } int main() { while(scanf("%d",&n)!=EOF && n) { scanf("%d",&m); memset(match, 0 ,sizeof(match)); for(int i= 1; i<= n; i++) for(int j= 1; j<= m; j++) scanf("%d",&map[i][j]); int ans= 0; for(int i= 1; i<= n; i++) { memset(visit, 0, sizeof(visit)); if(dfs(i)) ans++; } printf("%d\n",ans); } return 0; }