题目连接: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;
}