算法轮廓:
(1)置M为空
(2)找出一条增广路径P,通过取反操作获得更大的匹配M’代替M
(3)重复(2)操作直到找不出增广路径为止
下面是匈牙利算法的c语言模板:
#include
<
stdio.h
>
#include < cstring >
// 匈牙利算法
int xv = 5 ,yv = 5 ,n = 5 ; // 顶点数(数字5认你定)
int g[ 5 ][ 5 ]; // g[i][j]=1 表示 xi与yj相邻
int sy[ 5 ]; // 辅助:当轮被搜过的y点都是1
int cnt,xm[ 5 ],ym[ 5 ]; // 输出
void init()
{
cnt = 0 ;
memset(g, 0 , sizeof (g));
memset(xm, - 1 , sizeof (xm));
memset(ym, - 1 , sizeof (ym));
}
int path( int u) // 返回是否找到增广路(递归,时间复杂度O(n*n))
{
int v;
for (v = 0 ;v < yv;v ++ )
{
if ((g[u][v] == 1 ) && (sy[v] == 0 ))
{
sy[v] = 1 ;
if ((ym[v] ==- 1 ) || (path(ym[v]) == 1 ))
{
xm[u] = v;ym[v] = u;
return 1 ;
}
}
}
return 0 ;
}
void main()
{
int i,j;
// 初始化
init();
for (i = 0 ;i < n;i ++ )
{
for (j = 0 ;j < n;j ++ )
{
scanf( " %d " , & g[i][j]);
}
}
// 核心
for (i = 0 ;i < xv;i ++ )
{
if (xm[i] ==- 1 )
{
memset(sy, 0 , sizeof (sy));
cnt += path(i);
}
}
// 打印
printf( " sum=%d " ,cnt);
}
#include < cstring >
// 匈牙利算法
int xv = 5 ,yv = 5 ,n = 5 ; // 顶点数(数字5认你定)
int g[ 5 ][ 5 ]; // g[i][j]=1 表示 xi与yj相邻
int sy[ 5 ]; // 辅助:当轮被搜过的y点都是1
int cnt,xm[ 5 ],ym[ 5 ]; // 输出
void init()
{
cnt = 0 ;
memset(g, 0 , sizeof (g));
memset(xm, - 1 , sizeof (xm));
memset(ym, - 1 , sizeof (ym));
}
int path( int u) // 返回是否找到增广路(递归,时间复杂度O(n*n))
{
int v;
for (v = 0 ;v < yv;v ++ )
{
if ((g[u][v] == 1 ) && (sy[v] == 0 ))
{
sy[v] = 1 ;
if ((ym[v] ==- 1 ) || (path(ym[v]) == 1 ))
{
xm[u] = v;ym[v] = u;
return 1 ;
}
}
}
return 0 ;
}
void main()
{
int i,j;
// 初始化
init();
for (i = 0 ;i < n;i ++ )
{
for (j = 0 ;j < n;j ++ )
{
scanf( " %d " , & g[i][j]);
}
}
// 核心
for (i = 0 ;i < xv;i ++ )
{
if (xm[i] ==- 1 )
{
memset(sy, 0 , sizeof (sy));
cnt += path(i);
}
}
// 打印
printf( " sum=%d " ,cnt);
}
PKU-1469(一道经典简单的最大匹配题)我们只要把上面的模板修改一下就能解出这题:
下面是AC-Code:
#include
<
stdio.h
>
#include < string .h >
const int MAXN = 500 ;
int xv,yv,n; // 顶点数(数字5认你定)
int g[MAXN][MAXN]; // g[i][j]=1 表示 xi与yj相邻
int sy[MAXN]; // 辅助:当轮被搜过的y点都是1
int cnt,xm[MAXN],ym[MAXN]; // 输出
void init()
{
cnt = 0 ;
memset(g, 0 , sizeof (g));
memset(xm, - 1 , sizeof (xm));
memset(ym, - 1 , sizeof (ym));
}
int path( int u) // 返回是否找到增广路(递归,时间复杂度O(n*n))
{
int v;
for (v = 0 ;v < yv;v ++ )
{
if ((g[u][v] == 1 ) && (sy[v] == 0 ))
{
sy[v] = 1 ;
if ((ym[v] ==- 1 ) || (path(ym[v]) == 1 ))
{
xm[u] = v;ym[v] = u;
return 1 ;
}
}
}
return 0 ;
}
// 按模板作出修改
int main()
{
int i,j,s,t,da;
scanf( " %d " , & n);
for (s = 0 ;s < n;s ++ )
{
// 初始化
init();
scanf( " %d%d " , & xv, & yv);
for (i = 0 ;i < xv;i ++ )
{
scanf( " %d " , & t);
for (j = 0 ;j < t;j ++ )
{
scanf( " %d " , & da);
g[i][da - 1 ] = 1 ;
}
}
// 核心
for (i = 0 ;i < xv;i ++ )
{
if (xm[i] ==- 1 )
{
memset(sy, 0 , sizeof (sy));
cnt += path(i);
}
}
if (cnt == xv) printf( " YES " );
else printf( " NO " );
}
return 0 ;
}
#include < string .h >
const int MAXN = 500 ;
int xv,yv,n; // 顶点数(数字5认你定)
int g[MAXN][MAXN]; // g[i][j]=1 表示 xi与yj相邻
int sy[MAXN]; // 辅助:当轮被搜过的y点都是1
int cnt,xm[MAXN],ym[MAXN]; // 输出
void init()
{
cnt = 0 ;
memset(g, 0 , sizeof (g));
memset(xm, - 1 , sizeof (xm));
memset(ym, - 1 , sizeof (ym));
}
int path( int u) // 返回是否找到增广路(递归,时间复杂度O(n*n))
{
int v;
for (v = 0 ;v < yv;v ++ )
{
if ((g[u][v] == 1 ) && (sy[v] == 0 ))
{
sy[v] = 1 ;
if ((ym[v] ==- 1 ) || (path(ym[v]) == 1 ))
{
xm[u] = v;ym[v] = u;
return 1 ;
}
}
}
return 0 ;
}
// 按模板作出修改
int main()
{
int i,j,s,t,da;
scanf( " %d " , & n);
for (s = 0 ;s < n;s ++ )
{
// 初始化
init();
scanf( " %d%d " , & xv, & yv);
for (i = 0 ;i < xv;i ++ )
{
scanf( " %d " , & t);
for (j = 0 ;j < t;j ++ )
{
scanf( " %d " , & da);
g[i][da - 1 ] = 1 ;
}
}
// 核心
for (i = 0 ;i < xv;i ++ )
{
if (xm[i] ==- 1 )
{
memset(sy, 0 , sizeof (sy));
cnt += path(i);
}
}
if (cnt == xv) printf( " YES " );
else printf( " NO " );
}
return 0 ;
}