zoukankan      html  css  js  c++  java
  • 二分图匹配KM算法

    Kuhn-Munkres算法

    KM算法,求完备匹配下的最大权匹配,时间复杂度O(\(n^3\))
    所谓的完备匹配就是在二部图中,x点集中的所有点都有对应的匹配 且 y点集中所有的点都有对应的匹配 ,则称该匹配为完备匹配

    算法思想

    (1)初始化可行顶标的值;
    (2)用匈牙利算法寻找完备匹配;
    (3)若未找到完备匹配则修改可行顶标的值;
    (4)重复(2)(3)直到找到相等子图的完备匹配为止。

    模板

    #include <bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    #define cin(a) scanf("%d",&a)
    #define pii pair<int,int>
    #define ll long long
    #define gcd __gcd
    const int inf = 0x3f3f3f3f;
    const int maxn = 310;
    const int M = 1e9+7;
    int n,m,k,t;
    
    int a[maxn][maxn];          //图
    int ex_x[maxn];         //x期望能匹配到的y值
    int ex_y[maxn];         //y期望能匹配到的x值
    bool vis_x[maxn];           //标记是否访问
    bool vis_y[maxn];           //标记是否访问
    int match[maxn];        //y的匹配
    int slack[maxn];        //y的松弛,记录y最少还差多少期望值
    
    
    bool dfs(int x)
    {
        vis_x[x] = 1;
        for(int y = 0; y <= y; y++)
        {
            if(vis_y[y]) continue;
    
            int gap = ex_x[x]-ex_y[y]-a[x][y];
    
            if(gap == 0)        //如果符合要求
            {
                vis_y[y] = 1;
                if(match[y] == -1 || dfs(match[y]))     //如果y没有被匹配,或者y的x可以换另一个y
                {
                    match[y] = x;
                    return true;
                }
            }
            else        //不符合要求,我还差gap的期望值才能有匹配
            {
                slack[y] = min(slack[y],gap);
            }
        }
    }
    
    
    int km()
    {
        mem(match,-1);mem(ex_y,0);      //y期望的x是0
        mem(ex_x,0);            //初始化
        for(int i = 0; i < n; i++)      //x期望的y是最大的那个
        {
            for(int j = 0; j < n; j++)
            {
                ex_x[i] = max(ex_x[i],a[i][j]);
            }
        }
    
        for(int i = 0; i < n; i++)
        {
            mem(slack,inf);
            while (1)
            {
                mem(vis_x,0);mem(vis_y,0);
                if(dfs(i)) break;       //找到匹配
    
                //如果找不到
                int d = inf;
                for(int j = 0; j < n; j++)
                {
                    if(!vis_y[j])   d = min(d,slack[j]);
                }
    
                for(int j = 0; j < n; j++)      //降低期望
                {
                    if(vis_x[j]) ex_x[j] -= d;      
    
                    if(vis_y[j]) ex_y[j] += d;
                    else slack[j] -= d;
                }
            }
        }
    
        int res = 0;
        for(int i = 0; i < n; i++)
        {
            res += a[match[i]][i];
        }
        return res;
    }
    
    int main()
    {
    #ifdef ONLINE_JUDGE
    #else
        freopen("data.in", "r", stdin);
        //freopen("data.out", "w", stdout);
    #endif
        while (~cin(n))
        {
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < n; j++)
                {
                    cin(a[i][j]);
                }
            }
            printf("%d\n",km());
        }
        return 0;
    }
    

    例题

    http://acm.hdu.edu.cn/showproblem.php?pid=2255

    参考博客

    https://www.cnblogs.com/wenruo/p/5264235.html
    https://baike.baidu.com/item/KM算法

  • 相关阅读:
    JSONObject和JSONArray区别及基本用法
    MySQL中UTF8编码的数据在cmd下乱码
    js页面刷新跳转的几种方式及区别
    JS中使用EL表达式
    $.ajax()方法参数详解
    Firefox默认英文修改中文
    配置文件的相对地址和绝对地址设置
    IntelliJ IDEA设置统一编码utf-8
    java.lang.SecurityException: Prohibited package name:
    flask的多个url对应同一个视图函数
  • 原文地址:https://www.cnblogs.com/hezongdnf/p/12076192.html
Copyright © 2011-2022 走看看