KM算法计算带权二分图最优匹配
时间复杂度\(O(n^3)\)
模板题:hdu2255 奔小康赚大钱
const int maxn=310;
const int inf=0x3f3f3f3f;
int n;
int g[maxn][maxn],ex1[maxn],ex2[maxn],match[maxn],slack[maxn];
bool vis1[maxn],vis2[maxn];
bool dfs(int x){
vis1[x]=true;
for(int y=0;y<n;y++) {
if(vis2[y]) continue;
int gap=ex1[x]+ex2[y]-g[x][y];
if(gap==0){
vis2[y]=true;
if(match[y]==-1 || dfs(match[y])){
match[y]=x;
return true;
}
}
else{
slack[y]=min(slack[y],gap);
}
}
return false;
}
int KM(){
memset(match,-1,sizeof(match));
memset(ex2,0,sizeof(ex2));
for(int i=0;i<n;i++) {
ex1[i]=g[i][0];
for(int j=0;j<n;j++) {
ex1[i]=max(ex1[i],g[i][j]);
}
}
for (int i=0;i<n;i++) {
memset(slack,0x3f,sizeof(slack));
while(1){
memset(vis1,false,sizeof(vis1));
memset(vis2,false,sizeof(vis2));
if(dfs(i)) break;
int d=inf;
for (int j=0;j<n;j++)
if(!vis2[j]) d=min(d,slack[j]);
for (int j=0;j<n;j++){
if(vis1[j]) ex1[j]-=d;
if(vis2[j]) ex2[j]+=d;
else slack[j]-=d;
}
}
}
int res=0;
for(int i=0;i<n;i++)
res+=g[match[i]][i];
return res;
}