KM算法还是比较难理解,对那个很无语的”顶标”,还有一堆定理(表示不想看)~
但是代码还是比较好写,
它是基于匈牙利算法的二分图最大匹配。
思路就看这个神犇的博客吧! –>|传送门|<–
代码是进行了优化的:
时间复杂度O(n^3).
附上代码
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int inf=0x7fffffff,maxn=1010;
int w[maxn][maxn],link[maxn],lx[maxn],ly[maxn],slack[maxn];
bool visy[maxn],visx[maxn];
bool dfs(int node){
visx[node]=1;
For(i,1,m){
if(visy[i]) continue;
int ls=lx[node]+ly[i]-w[node][i];
if(ls==0){
visy[i]=1;
if(link[i]==-1 || dfs(link[i])){
link[i]=node;
return 1;
}
}
if(ls<slack[i])
slack[i]=ls;
}
return 0;
}
int km(){
int sum=0;
ak(ly);
For(i,1,n){
lx[i]=-inf;
For(j,1,n){
if(lx[i]<w[i][j])
lx[i]=w[i][j];
}
}
memset(link,-1,sizeof(link));
For(i,1,n){
For(j,1,m) slack[j]=inf;
while(1){
ak(visx),ak(visy);
if(dfs(i)) break;
int d=inf;
For(j,1,m){
if(!visy[j] && slack[j]<d)
d=slack[j];
}
For(j,1,n)
if(visx[j])
lx[j]-=d;
For(j,1,m)
if(visy[j])
ly[j]+=d;
else slack[j]-=d;
}
}
For(i,1,m){
if(link[i]>-1){
sum+=w[link[i]][i];
}
}
return sum;
}
上面的博客对这写细节进行了解析,在此不进行赘述。