#define MAXN 10 //MAXN为表示X集合和Y集合顶点个数最大值的符号常量 int nx, ny; //X和Y集合中顶点的个数 int g[MAXN][MAXN]; //邻接矩阵,g[i][j]为1表示Xi和Yj有边相连 int cx[MAXN] , cy[MAXN]; //cx[i]表示最终求得的最大匹配中与Xi匹配的Y顶点, cy[i]同理
DFS增广
//DFS算法中记录顶点访问状态的数组,mk[i] = 0表示未访问过,为1表示访问过 int mk[MAXN] ; //从X集合中的顶点u出发,用深度优先的策略寻找增广路 //(这种增广路只能使当前的匹配数增加1) int path( int u ) { for( int v = 0 ; v < ny ; v++ ) //考虑所有Yi顶点v { if( g[u][v] && !mk[v] ) //v与u邻接,且没有访问过 { mk[v] = 1; //访问v //如果v没有匹配,或者v已经匹配了,但从cy[v]出发可以找到一条增广路 if( cy[v] == -1 || path( cy[v] ) ) //注意如果前一个条件成立,则不会递归调用 { cx[u] = v; //把v匹配给u cy[v] = u; //把u匹配给v return 1; //找到可增广路 } } } return 0 ; //如果不存在从u出发的增广路 } int MaxMatch( ) //求二部图最大匹配的匈牙利算法 { int res = 0; //所求得的最大匹配 memset( cx , 0xff , sizeof(cx) ) ; //从0匹配开始增广, 将cx和cy各元素初始化为-1 memset( cy , 0xff , sizeof(cy) ) ; for( int i = 0 ; i <= nx ; i++ ) { if( cx[i] == -1 ) //从每个未盖点出发进行寻找增广路 { memset( mk , 0 , sizeof(mk) ) ; res += path(i) ; //每找到一条增广路,可使得匹配数加1 } } return res; }
用BFS增广
int pred[MAXN]; //是用来记录交错轨的,同时也用来记录Y集合中的顶点是否遍历过 int queue[MAXN]; //实现BFS搜索用到的队列(用数组模拟) int MaxMatch( ) { int i, j, y; int cur, tail; //表示队列头和尾位置的下标 int res = 0; //所求得的最大匹配数 memset( cx , 0xff , sizeof(cx) ); //初始化所有点为未被匹配的状态 memset( cy , 0xff , sizeof(cy) ); for( i = 0; i < nx; i++ ) { if( cx[i] != -1 ) continue; //对X集合中的每个未盖点i进行一次BFS找交错轨 for( j = 0; j < ny; j++ ) pred[j] = -2; //-2表示初始值 cur = tail = 0; //初始化BFS的队列 for( j = 0; j < ny; j++ ) //把i的邻接点顶都入队列 { if( g[i][j] ) { pred[j] = -1; queue[tail++] = j; //-1表示遍历到,是邻接顶点 } } while( cur < tail ) //BFS { y = queue[cur]; if( cy[y] == -1 ) break; //找到一个未被匹配的点,则找到了一条交错轨 cur++; //y已经被匹配给cy[y]了,从cy[y]出发,将它的邻接顶点入队列 for( j = 0; j < ny; j++ ) { if( pred[j] == -2 && g[cy[y]][j] ) { pred[j] = y; queue[tail++] = j; } } } if( cur == tail ) continue; //没有找到交错轨 while( pred[y] > -1 ) //更改交错轨上匹配状态 { cx[ cy[ pred[y] ] ] = y; cy[y] = cy[ pred[y] ]; y = pred[y]; } cy[y] = i; cx[i] = y; res++; //匹配数加1 } return res; }
可通过zoj1654 zoj1364 zoj1140 巩固