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;