题目大意
给出n*n表格,第a[i,j]表示i到j的权值,现在我们要将每个a[i,j]=sum[j]-a[i,j],
求出当前二分图a[][]最小匹配
最小匹配只需将权值取负后,求二分图最大匹配,使用km算法(即之前blog中代码稍微改了一下)
#include<iostream> #include<cstdio> #include<string.h> using namespace std; int lx[200],ly[200],w[200][200],pre[200]; int n,ans,mi; bool sx[200],sy[200]; bool path(int p){ sx[p]=1; int i; for(i=1;i<=n;i++) if (!sy[i]&&lx[p]+ly[i]==w[p][i]){ sy[i]=1; if (pre[i]==0||path(pre[i])){ pre[i]=p; return 1; } } return 0; } int main() { int i,j,k; scanf("%d",&n); for(i=1;i<=n;i++) lx[i]=-10000000; for(i=1;i<=n;i++) for(j=1;j<=n;j++){ scanf("%d",&w[i][j]); w[n+1][j]+=w[i][j]; } for(i=1;i<=n;i++) for(j=1;j<=n;j++){ w[i][j]=-(w[n+1][j]-w[i][j]); if (w[i][j]>lx[i]) lx[i]=w[i][j]; } for(i=1;i<=n;i++){ memset(sx,0,sizeof(sx)); memset(sy,0,sizeof(sy)); while (!path(i)){ mi=2000000000; for(j=1;j<=n;j++) for(k=1;k<=n;k++) if (sx[j]&&!sy[k]){ if (lx[j]+ly[k]-w[j][k]<mi) mi=lx[j]+ly[k]-w[j][k]; } for(j=1;j<=n;j++) if(sx[j]) lx[j]-=mi; for(j=1;j<=n;j++) if(sy[j]) ly[j]+=mi; memset(sx,0,sizeof(sx)); memset(sy,0,sizeof(sy)); } } for(i=1;i<=n;i++) ans+=-(lx[i]+ly[i]); printf("%d",ans); return 0; }