题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2255
二分图带全匹配的裸题,直接贴板子就行,对于二分图最佳匹配可以用网络流去写,还有KM算法也可以解决这个问题,这个算法的中心思想就是依次选择最大权的边构造子图,然后引入了顶标概念,我是看这篇博客学习的,讲的很nice,二分图匹配之最佳匹配——KM算法
AC代码:
#include <bits/stdc++.h>
#define maxn 305
#define inf 0x7fffffff
using namespace std;
int w[maxn][maxn];
int pre[maxn], cx[maxn], cy[maxn];
bool usex[maxn], usey[maxn];
int n,m,ans;
void init(){
memset(cy, 0, sizeof(cy));
memset(cx, 0, sizeof(cx));
memset(w, 0, sizeof(w));
memset(pre, -1, sizeof(pre));
}
bool dfs(int u){
usex[u] = true;
for(int v=1;v<=n;v++){
if(usey[v] == false && cx[u] + cy[v] == w[u][v]){
usey[v] = true;
if(pre[v] == -1 || dfs(pre[v])){
pre[v] = u;
return true;
}
}
}
return false;
}
int km(){
for(int i=1;i<=n;i++){
while(true){
int d = inf;
memset(usex, false, sizeof(usex));
memset(usey, false, sizeof(usey));
if( dfs(i) ) break;
for(int j=1;j<=n;j++){
if(usex[j] == true){
for(int k=1;k<=n;k++){
if(usey[k] == false) d = min(d, cx[j] + cy[k] - w[j][k]);
}
}
}
if(d == inf) return -1;
for(int j=1;j<=n;j++) if(usex[j] == true) cx[j] -= d;
for(int j=1;j<=n;j++) if(usey[j] == true) cy[j] += d;
}
}
ans = 0;
for(int i=1;i<=n;i++){
ans += w[pre[i]][i];
}
return ans;
}
int main()
{
while(~scanf("%d",&n)){
init();
for(int i=1;i<=n;i++){
int xx = 0;
for(int j=1;j<=n;j++){
scanf("%d",&w[i][j]);
xx = max(xx, w[i][j]);
}
cx[i] = xx;
}
int ans = km();
printf("%d\n", ans);
}
return 0;
}