KM算法是求最大权完备匹配,如果要求最小权完备匹配怎么办?方法很简单,只需将所有的边权值取其相反数,求最大权完备匹配,匹配的值再取相反数即可。
KM算法的运行要求是必须存在一个完备匹配,如果求一个最大权匹配(不一定完备)该如何办?依然很简单,把不存在的边权值赋为0。
KM算法求得的最大权匹配是边权值和最大,如果我想要边权之积最大,又怎样转化?还是不难办到,每条边权取自然对数,然后求最大和权匹配,求得的结果a再算出e^a就是最大积匹配。至于精度问题则没有更好的办法了
class match{
public:
int lx[N],ly[N];
int Stack[N],next[N];
bool visx[N],visy[N];
int n;
vector<int>vec[N];
void init()
{
rep(i,n+1) vec[i].clear();
memset(next,-1,sizeof(next));
}
bool bfs(int u)
{
visx[u]=true;
rep(i,vec[u].size())
{
if(visy[i]==true) continue;
if(lx[u]+ly[i]==vec[u][i])
{
visy[i]=true;
if(next[i]==-1 || bfs(next[i]))
{
next[i]=u; return true;
}
}
else
Stack[i]=min(Stack[i],lx[u]+ly[i]-vec[u][i]);
}
return false;
}
int km()
{
rep(i,n) lx[i]=-inf;
rep(i,n)
{
ly[i]=0;
rep(j,n)
lx[i]=max(lx[i],vec[i][j]);
}
rep(i,n)
{
while(true)
{
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
rep(j,n) Stack[j]=inf;
if(bfs(i)) break;
int Min=inf;
rep(j,n)
if(visy[j]==false)
Min=min(Min,Stack[j]);
rep(j,n)
{
if(visx[j]==true) lx[j]-=Min;
if(visy[j]==true) ly[j]+=Min;
}
}
}
int ans=0;
rep(i,n)
ans+=vec[next[i]][i];
return ans;
}
};
match sa;