const int N = 505;
const int INF = 1<<30;
int ex_boy[N],ex_girl[N]; // 左右期望值
bool vis_girl[N],vis_boy[N]; // 访问标记
int love[N][N]; // 期望值矩阵
int match[N]; // 右图匹配点
int d[N]; // 期望差值
bool find_lover(int girl,int m)
{
vis_girl[girl] = true;
for(int i = 0 ; i < m ; i ++)
{
if(vis_boy[i]) continue;
int dis = ex_girl[girl]+ex_boy[i] - love[girl][i];
if(dis == 0)
{
vis_boy[i] = 1;
if(match[i] == -1 || find_lover(match[i],m))
{
match[i] = girl;
return true;
}
}
else
d[i] = min(d[i],dis);
}
return false;
}
int KM(int n,int m)
{
for(int i = 0 ; i < m ; i ++) ex_boy[i] = 0;
for(int i = 0 ; i < m ; i ++) match[i] = -1;
for(int i = 0 ; i < n ; i ++)
{
ex_girl[i] = love[i][0];
for(int j = 1 ;j < m ; j ++)
ex_girl[i] = max(ex_girl[i],love[i][j]);
}
for(int i = 0 ; i < n ; i ++)
{
for(int j = 0 ; j < m ; j ++) d[j] = INF;
while(1)
{
for(int j = 0 ; j < n ; j ++) vis_girl[j] = 0;
for(int j = 0 ; j < m ; j ++) vis_boy[j] = 0;
if(find_lover(i,m)) break;
int dis = INF;
for(int j = 0 ; j < m ; j ++)
if(!vis_boy[j]) dis=min(dis,d[j]);
for(int j = 0 ; j < max(n,m) ; j ++)
{
if(vis_girl[j]) ex_girl[j] -= dis;
if(vis_boy[j]) ex_boy[j] += dis;
}
}
}
int res = 0;
for(int i = 0 ; i < m ; i ++)
{
res += love[match[i]][i];
}
return res;
}
模板:KM匹配
最新推荐文章于 2020-09-24 20:58:55 发布