二分图带权最大匹配的KM算法(朴素版)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
using namespace std;
int init(){
int rv=0,fh=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
rv=(rv<<1)+(rv<<3)+c-'0';
c=getchar();
}
return fh*rv;
}
int n,wei[305][305],lx[305],ly[305],match[305];
bool f[305],fx[305],fy[305];
bool hungarian(int u){
fx[u]=1;
for(int v=1;v<=n;v++){
if(!fy[v]&&lx[u]+ly[v]==wei[u][v]){
fy[v]=1;
if(!match[v]||hungarian(match[v])){
match[v]=u;
return 1;
}
}
}
return 0;
}
int main(){
while(~scanf("%d",&n)){
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
memset(wei,0,sizeof(wei));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
wei[i][j]=init();
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
lx[i]=max(lx[i],wei[i][j]);
}
}
memset(match,0,sizeof(match));
for(int i=1;i<=n;i++){
while(1){
memset(fx,0,sizeof(fx));
memset(fy,0,sizeof(fy));
if(hungarian(i)) break;
int ma=0x3f3f3f3f;
for(int k=1;k<=n;k++){
if(fx[k]){
for(int j=1;j<=n;j++){
if(!fy[j]&&(lx[k]+ly[j]-wei[k][j])<ma){
ma=lx[k]+ly[j]-wei[k][j];
}
}
}
}
for(int i=1;i<=n;i++){
if(fx[i]) lx[i]-=ma;
if(fy[i]) ly[i]+=ma;
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(match[i]) ans+=wei[match[i]][i];
}
cout<<ans<<endl;
}
}