O(n^3)的复杂度,解决最佳完备匹配问题。
#include <cstdio> #include <cstring> using namespace std; const int maxn=160,OO=(~(0U))>>1; int w[maxn][maxn]; int lx[maxn],ly[maxn]; int linky[maxn]; int visx[maxn],visy[maxn]; int N; int slack[maxn]; void input(){ scanf("%d",&N); for(int i=0;i<N;++i) for(int j=0;j<N;++j) scanf("%d",&w[i][j]); } bool find(int x){ visx[x]=true; for(int y=0;y<N;++y){ if(visy[y])continue; int t=lx[x]+ly[y]-w[x][y]; if(t==0){ visy[y]=true; if(linky[y]==-1||find(linky[y])){ linky[y]=x; return true; } } else{ if(slack[y]>t) slack[y]=t; } } return false; } void KM(){ memset(linky,-1,sizeof(linky)); memset(lx,0,sizeof(lx)); memset(ly,0,sizeof(ly)); for(int i=0;i<N;++i) for(int j=0;j<N;++j) if(w[i][j]>lx[i]) lx[i]=w[i][j]; for(int x=0;x<N;++x){ for(int i=0;i<N;++i) slack[i]=OO; while(1){ memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(find(x))break; int d=OO; for(int i=0;i<N;++i){ if(!visy[i]) if(d>slack[i]) d=slack[i]; } for(int i=0;i<N;++i){ if(visx[i]) lx[i]-=d; } for(int i=0;i<N;++i){ if(visy[i]) ly[i]+=d; else slack[i]-=d; //不太明白slack的操作 } } } } void output(){ int res=0; for(int j=0;j<N;++j){ for(int i=0;i<N;++i) res+=w[i][j]; res-=w[linky[j]][j]; } printf("%d\n",res); } int main(){ input(); KM(); output(); }
崔天翼神牛的模板http://cuitianyi.com/blog/%E6%B1%82%E6%9C%80%E5%A4%A7%E6%9D%83%E4%BA%8C%E5%88%86%E5%8C%B9%E9%85%8D%E7%9A%84km%E7%AE%97%E6%B3%95/