宋壬初吧 关注:25贴子:419
  • 3回复贴,共1

KM算法求二分图最佳匹配

只看楼主收藏回复


#include <cstdio>
#include <memory.h>
#include <algorithm>    // 使用其中的 min 函数
using namespace std;
const int MAX = 1024;
int n;                // X 的大小
int weight [MAX] [MAX];        // X 到 Y 的映射(权重)
int lx [MAX], ly [MAX];        // 标号
bool sx [MAX], sy [MAX];    // 是否被搜索过
int match [MAX];        // Y(i) 与 X(match [i]) 匹配
// 初始化权重
void init (int size);
// 从 X(u) 寻找增广道路,找到则返回 true
bool path (int u);
// 参数 maxsum 为 true ,返回最大权匹配,否则最小权匹配
int bestmatch (bool maxsum = true);
void init (int size)
{
    // 根据实际情况,添加代码以初始化
    n = size;
    for (int i = 0; i < n; i ++)
        for (int j = 0; j < n; j ++)
            scanf ("%d", &weight [i] [j]);
}
bool path (int u)
{
    sx [u] = true;
    for (int v = 0; v < n; v ++)
        if (!sy [v] && lx[u] + ly [v] == weight [u] [v])
            {
            sy [v] = true;
            if (match [v] == -1 || path (match [v]))
                {
                match [v] = u;
                return true;
                }
            }
    return false;
}
int bestmatch (bool maxsum)
{
    int i, j;



IP属地:上海1楼2009-05-16 11:43回复
        if (!maxsum)
            {
            for (i = 0; i < n; i ++)
                for (j = 0; j < n; j ++)
                    weight [i] [j] = -weight [i] [j];
            }
        // 初始化标号
        for (i = 0; i < n; i ++)
            {
            lx [i] = -0x1FFFFFFF;
            ly [i] = 0;
            for (j = 0; j < n; j ++)
                if (lx [i] < weight [i] [j])
                    lx [i] = weight [i] [j];
            }
        memset (match, -1, sizeof (match));
        for (int u = 0; u < n; u ++)
            while (1)
                {
                memset (sx, 0, sizeof (sx));
                memset (sy, 0, sizeof (sy));
                if (path (u))
                    break;
                // 修改标号
                int dx = 0x7FFFFFFF;
                for (i = 0; i < n; i ++)
                    if (sx [i])
                        for (j = 0; j < n; j ++)
                            if(!sy [j])
                                dx = min (lx[i] + ly [j] - weight [i] [j], dx);
    


    IP属地:上海2楼2009-05-16 11:43
    回复
                  for (i = 0; i < n; i ++)
                      {
                      if (sx [i])
                          lx [i] -= dx;
                      if (sy [i])
                          ly [i] += dx;
                      }
                  }
          int sum = 0;
          for (i = 0; i < n; i ++)
              sum += weight [match [i]] [i];
          if (!maxsum)
              {
              sum = -sum;
              for (i = 0; i < n; i ++)
                  for (j = 0; j < n; j ++)
                      weight [i] [j] = -weight [i] [j];         // 如果需要保持 weight [ ] [ ] 原来的值,这里需要将其还原
              }
          return sum;
      }
      int main()
      {
          int n;
          scanf ("%d", &n);
          init (n);
          int cost = bestmatch (true);
          printf ("%d ", cost);
          for (int i = 0; i < n; i ++)
              {
              printf ("Y %d -> X %d ", i, match [i]);
              }
          return 0;
      } 


      IP属地:上海3楼2009-05-16 11:43
      回复
        维护贴吧秩序,人工置顶


        4楼2010-06-13 23:54
        回复