首页 > 其他分享 >最大权匹配问题,KM模板

最大权匹配问题,KM模板

时间:2023-08-03 20:23:41浏览次数:48  
标签:匹配 int wl KM MAXN nl nr 模板

class KM
{
public:
    // MAXN 最大点数       oo 无穷大
    static const int MAXN = 405, oo = 1000101010;
    int nl, nr, m; // 左边的点数,右边的点数,边数
    int result[MAXN]; // 左边点最大权匹配的匹配
    long long ans;
    KM(int nl, int nr, int m) : nl(nl), nr(nr), m(m) {init(); }
    void init()
    {
        if(nr < nl)
            nr = nl; // necessary for algorithm correctness
        for(int i = 1; i <= nl; i++)
            memset(e[i], 0, (nr + 1) * sizeof(int));
        memset(matchl, 0, (nl + 1) * sizeof(int));
        memset(matchr, 0, (nr + 1) * sizeof(int));
        memset(visitl, 0, (nl + 1) * sizeof(int));
        memset(visitr, 0, (nr + 1) * sizeof(int));
        memset(wl, 0, (nl + 1) * sizeof(int));
        memset(wr, 0, (nr + 1) * sizeof(int));
        vn = 0;
    }
    void insert(int u, int v, int w)
    { // 加边
        e[u][v] = w;
        if(w > wl[u])
            wl[u] = w;
    }
    pair<long long, int *> solve()
    { // ans 最大权匹配的权 result 最大权匹配的匹配
        for(int i = 1; i <= nl; i++)
            bfs(i);
        ans = 0;
        for(int i = 1; i <= nl; i++)
            ans += e[i][matchl[i]];
        for(int i = 1; i <= nl; i++)
            result[i] = e[i][matchl[i]] ? matchl[i] : 0;
        return make_pair(ans, result);
    }
private:
    void found(int x)
    {
        while(x)
        {
            int tmp = matchl[prev[x]];
            matchr[x] = prev[x];
            matchl[prev[x]] = x;
            x = tmp;
        }
    }
    void bfs(int st)
    {
        memset(slack, 63, (nr + 1) * sizeof(int));
        while(!q.empty())
            q.pop();
        vn++;
        visitl[st] = vn;
        q.push(st);
        while(1)
        {
            while(!q.empty())
            {
                int now = q.front(), tmp;
                q.pop();
                for(int i = 1; i <= nr; i++)
                    if(visitr[i] != vn && (tmp = wl[now] + wr[i] - e[now][i]) <= slack[i])
                    {
                        prev[i] = now;
                        if(!tmp)
                        {
                            visitr[i] = vn;
                            if(!matchr[i])
                                return found(i);
                            else
                                visitl[matchr[i]] = vn, q.push(matchr[i]);
                        }
                        else
                            slack[i] = tmp;
                    }
            }
            int d = oo;
            for(int i = 1; i <= nr; i++)
                if(visitr[i] != vn)
                    d = min(d, slack[i]);
            if(d == oo)
                return;
            for(int i = 1; i <= nl; i++)
                if(visitl[i] == vn)
                    wl[i] -= d;
            for(int i = 1; i <= nr; i++)
                if(visitr[i] == vn)
                    wr[i] += d;
                else
                    slack[i] -= d;
            for(int i = 1; i <= nr; i++)
                if(visitr[i] != vn && !slack[i])
                {
                    visitr[i] = vn;
                    if(!matchr[i])
                        return found(i);
                    else
                        visitl[matchr[i]] = vn, q.push(matchr[i]);
                }
        }
    }
    queue<int> q;
    int wl[MAXN], wr[MAXN], slack[MAXN], prev[MAXN], matchl[MAXN], matchr[MAXN], visitl[MAXN], visitr[MAXN], vn;
    int e[MAXN][MAXN];
};

 

class KM { public:     // MAXN 最大点数       oo 无穷大     static const int MAXN = 405, oo = 1000101010;     int nl, nr, m; // 左边的点数,右边的点数,边数     int result[MAXN]; // 左边点最大权匹配的匹配     long long ans;     KM(int nl, int nr, int m) : nl(nl), nr(nr), m(m) {init(); }     void init()     {         if(nr < nl)             nr = nl; // necessary for algorithm correctness         for(int i = 1; i <= nl; i++)             memset(e[i], 0, (nr + 1) * sizeof(int));         memset(matchl, 0, (nl + 1) * sizeof(int));         memset(matchr, 0, (nr + 1) * sizeof(int));         memset(visitl, 0, (nl + 1) * sizeof(int));         memset(visitr, 0, (nr + 1) * sizeof(int));         memset(wl, 0, (nl + 1) * sizeof(int));         memset(wr, 0, (nr + 1) * sizeof(int));         vn = 0;     }     void insert(int u, int v, int w)     { // 加边         e[u][v] = w;         if(w > wl[u])             wl[u] = w;     }     pair<long long, int *> solve()     { // ans 最大权匹配的权 result 最大权匹配的匹配         for(int i = 1; i <= nl; i++)             bfs(i);         ans = 0;         for(int i = 1; i <= nl; i++)             ans += e[i][matchl[i]];         for(int i = 1; i <= nl; i++)             result[i] = e[i][matchl[i]] ? matchl[i] : 0;         return make_pair(ans, result);     } private:     void found(int x)     {         while(x)         {             int tmp = matchl[prev[x]];             matchr[x] = prev[x];             matchl[prev[x]] = x;             x = tmp;         }     }     void bfs(int st)     {         memset(slack, 63, (nr + 1) * sizeof(int));         while(!q.empty())             q.pop();         vn++;         visitl[st] = vn;         q.push(st);         while(1)         {             while(!q.empty())             {                 int now = q.front(), tmp;                 q.pop();                 for(int i = 1; i <= nr; i++)                     if(visitr[i] != vn && (tmp = wl[now] + wr[i] - e[now][i]) <= slack[i])                     {                         prev[i] = now;                         if(!tmp)                         {                             visitr[i] = vn;                             if(!matchr[i])                                 return found(i);                             else                                 visitl[matchr[i]] = vn, q.push(matchr[i]);                         }                         else                             slack[i] = tmp;                     }             }             int d = oo;             for(int i = 1; i <= nr; i++)                 if(visitr[i] != vn)                     d = min(d, slack[i]);             if(d == oo)                 return;             for(int i = 1; i <= nl; i++)                 if(visitl[i] == vn)                     wl[i] -= d;             for(int i = 1; i <= nr; i++)                 if(visitr[i] == vn)                     wr[i] += d;                 else                     slack[i] -= d;             for(int i = 1; i <= nr; i++)                 if(visitr[i] != vn && !slack[i])                 {                     visitr[i] = vn;                     if(!matchr[i])                         return found(i);                     else                         visitl[matchr[i]] = vn, q.push(matchr[i]);                 }         }     }     queue<int> q;     int wl[MAXN], wr[MAXN], slack[MAXN], prev[MAXN], matchl[MAXN], matchr[MAXN], visitl[MAXN], visitr[MAXN], vn;     int e[MAXN][MAXN]; };

标签:匹配,int,wl,KM,MAXN,nl,nr,模板
From: https://www.cnblogs.com/chayi/p/17604351.html

相关文章

  • 微信公众号发模板消息(spring集成)
    引入依赖:<dependency><groupId>me.chanjar</groupId><artifactId>weixin-java-mp</artifactId><version>1.3.3</version></dependency> 其中已实现的功能:publicinter......
  • T4 模板: 为 ASP.NET MVC 开发人员快速入门指南
    http://blogs.msdn.com/b/webdev/archive/2009/01/29/t4-templates-a-quick-start-guide-for-asp-net-mvc-developers.aspx 在中提到我们的最近博客文章,ASP.NETMVC发布候选版,我们的代码生成功能(即,添加控制器和添加视图)现在使用T4(文本模板转换工具包)模板化技术在幕后。因为......
  • KMP与Trie
    KMP算法KMP算法用于解决字串与母串的匹配问题,可看作哈希的简单写法,时间复杂度O(m+n)KMP算法的核心优势在于相对于暴力枚举,它可以省去重复的步骤,从而将匹配过程由O(mn)优化为近似O(2m),该算法的核心在于寻找子串前缀与后缀重合的最大长度,也就是next数组,那么怎么求呢?就是将子串自匹......
  • protoc-gen-doc 自定义模板规则详解
    protoc-gen-doc自定义模板规则详解配套演示工程此项目中所用proto文件位于./proto目录下,来源于官方proto示例此项目中所列所有模板case文件位于./tmpl目录下此教程均基于markdown文本演示前言最近有通过proto文件生成其接口文档的需求,而protoc-gen-doc所生成......
  • 【SpringBoot学习】1、SpringBoot 配置 jsp 模板引擎
    springboot整合jsp页面创建springboot项目就不废话了。在原来的基础上直接加东西就可以了1、添加jsp支持的jar包<!--servlet依赖--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><scope>provid......
  • bp安装+匹配规则(防止抓火狐的多余包)
    bp安装使用BurpLoaderKeygen.jar:2c8c7b95640f31985f83580402f26a06b78c55877fa33ef1f9d14d2ebb2d8ecdburpsuite_pro_v2023.6.jar:e49caa5a2c01dcad37ecc95c1779f46b8abe7fdfd46ce756c821834903fcb759哈希值校验命令:Get-FileHashC:\Users\amtec\Desktop\test\burpsuite_p......
  • Tita 升级|总结模板,满足多种管理要求
    升级详情一、【总结】支持自定义总结模板「总结模板」菜单1.都谁可见总结管理员、超管、老板、助理可见总结模板菜单,并可查看系统模板与公司的所有自定义模板;当你被授权为某个自定义菜单的管理员时,也可看到总结模板菜单与被授权管理的模板;注意:系统模板不可编辑,仅总结管......
  • 快读模板
    inline__int128read(){__int128x=0,f=1;charch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0�......
  • 模板的简单使用
    这篇博客主要是简单的介绍函数模板和类模板的使用。函数模板假设现在需要你写多个交换函数用于各种类型的交换,如果一个一个写的话那即浪费时间,也会让代码整体不好看。那么为了解决这种情况就可以使用函数模板。例如下面:usingnamespacestd;//模板函数template<classT>//如果你......
  • java枚举类模板
    importcom.alibaba.fastjson.JSONObject;importlombok.Getter;@GetterpublicenumMedDoctorStatusEnum{ONLINE(0,"上线"),A_SHORT_BREAK(1,"小憩"),OFFLINE(2,"离线");privateIntegercode;privateStringdesc;MedDoct......