int Max( int a,int b )
{
return a>=b?a:b;
}
bool findpath(int u) //给x[u]找匹配,这个过程和匈牙利匹配是一样的
{
visx[u] = 1;
for( int v=1; v<=ny; v++ )
{
if( !visy[v] && lx[u] + ly[v] == map[u][v] )
{
visy[v] = 1;
if( cy[v]==-1 || findpath( cy[v] ) )
{
cy[v] = u;
cx[u] = v;
return true;
}
}
}
return false;
}
int KM_perfect_match()
{
int ans = 0;
int slack;
memset( cx,-1,sizeof(cx) );
memset( cy,-1,sizeof(cy) );
memset( lx,0,sizeof(lx) );
memset( ly,0,sizeof(ly) );
for( int i = 1; i <= nx; i ++ )
{
for( int j = 1; j <= ny; j ++ )
{
lx[i] = Max( lx[i],map[i][j] ); //lx[i]为i点权值最大的边
}
//if( lx[i] == -1 )
// return -1; //无法匹配
}
for( int k = 1; k <= nx; k ++ ) //为x里的每一个点找匹配 不断修改顶标,直到找到完备匹配或完美匹配
{
while(1)
{
memset( visx,0,sizeof(visx) );
memset( visy,0,sizeof(visy) );
if( cx[k] == -1 && findpath(k) )
break;
else //匹配失败,找最小值
{
slack = inf;
for( int i = 1; i <= nx; i ++ )
{
if( visx[i] )
{
for( int j = 1; j <= ny; j ++ )
{
if( !visy[j] && slack > lx[i] + ly[j] - map[i][j] )
slack = lx[i] + ly[j] - map[i][j];
}
}
}
for( int i = 1; i <= nx; i ++ )
{
if( visx[i] )
lx[i] -= slack;
if( visy[i] )
ly[i] += slack;
}
}
}
}
for( int i = 1; i <= nx; i ++ ) //权值相加
ans += map[cy[i]][i];
return ans;
}
KM模板
最新推荐文章于 2021-08-03 11:15:51 发布