带权二分图匹配KM算法

二分图带权匹配(推箱子问题的思考) 转载请附上原文链接: http://blog.youkuaiyun.com/u013351484/article/details/51598270 二分图带权匹配(也叫二分图最优(最佳)匹配,Kuhn-Munkres 算法) 预备知识:二分图最大匹配,二分图完备(完美)匹配 二分图带权匹配,可以把它看作集合 X 的每个顶点到集合 Y 的每个顶点均有边的二分图(设权重均为正数,则原来分别... 阅读详情
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=1e9;
int flag;
struct zp
{
    int x,y;
}man[200],house[200];
int x[200][200],mn,ho,lx[200],ly[200];
void build_map()//建图,单向图
{
    for(int i=0; i<mn; i++)
    {
        for(int j=0; j<ho; j++)
        {
            x[i+1][j+1]=abs(man[i].x-house[j].x)+abs(man[i].y-house[j].y);
        }
    }
}
int visx[200],visy[200],dis[200],ans;
int dfspath(int k)//匈牙利算法,寻找路径
{
    visx[k]=1;
    for(int i=1; i<=mn; i++)
    {
        if(!visy[i]&&lx[k]+ly[i]==x[k][i])
        {
            visy[i]=1;
            if(dis[i]==-1||dfspath(dis[i]))
            {
                dis[i]=k;
                return 1;
            }
        }
    }
    return 0;
}
int KM()
{
    if(!flag)//最小权值处理
    {
        for(int i=1;i<=mn;i++)
            for(int j=1;j<=ho;j++)
            x[i][j]=-x[i][j];
    }
    for(int i=1;i<=mn;i++)//初始化x点集标号
    {
        lx[i]=x[i][1];
        for(int j=2;j<=ho;j++)
            lx[i]=max(lx[i],x[i][j]);
    }
    memset(ly,0,sizeof(ly));//初始化y点集标号
    memset(dis,-1,sizeof(dis));//保存对应关系
    for(int i=1; i<=mn; i++)
    {
        while(1)
        {
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(dfspath(i))//找到路径
                break;
                int Min=INF+1;
                for(int j=1;j<=mn;j++)//扩大子图范围
                {
                    if(visx[j])
                        for(int k=1;k<=ho;k++)
                        if(!visy[k])
                        Min=min(Min,lx[j]+ly[k]-x[j][k]);
                }
                for(int j=1;j<=mn;j++)//更新x点集标号
                    if(visx[j])
                    lx[j]-=Min;
                for(int j=1;j<=ho;j++)//更新y点集标号
                    if(visy[j])
                    ly[j]+=Min;
        }
    }
    ans=0;
    for(int i=1;i<=ho;i++)//计算权值和1
        ans+=x[dis[i]][i];
        if(!flag)//求最小权值
            ans=-ans;
        return ans;//返回权值
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        mn=ho=0;
        char a[200];
        memset(x,0,sizeof(x));
        //flag=1;//最大权匹配
        flag=0;//最小权匹配 ,把权值取反然后求最大权匹配然后把结果取反
        for(int i=0; i<n; i++)
        {
            scanf("%s",a);
            for(int j=0; j<m; j++)
            {
                if(a[j]=='m') man[mn].x=i+1,man[mn++].y=j+1;
                else if(a[j]=='H') house[ho].x=i+1,house[ho++].y=j+1;
            }
        }
        build_map();
        printf("%d\n",KM());
    }
}

上面题目链接
题目大概意思是让求所有的m到H走的所有路之和最小,每一个H只能承载1个m。
KM的一点优化,有两种方式
hdu 2255题目
一般解法:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=1e9;
int flag;
int x[500][500],n,lx[500],ly[500];
int visx[500],visy[500],dis[500],ans;
int dfspath(int k)//匈牙利算法,寻找路径
{
    visx[k]=1;
    for(int i=0; i<n; i++)
    {
        if(!visy[i]&&lx[k]+ly[i]==x[k][i])
        {
            visy[i]=1;
            if(dis[i]==-1||dfspath(dis[i]))
            {
                dis[i]=k;
                return 1;
            }
        }
    }
    return 0;
}
int KM()
{
//    if(!flag)//最小权值处理
//    {
//        for(int i=0;i<=n;i++)
//            for(int j=0;j<n;j++)
//            x[i][j]=-x[i][j];
//    }
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));//初始化y点集标号
    memset(dis,-1,sizeof(dis));//保存对应关系
    for(int i=0; i<n; i++) //初始化x点集标号
        for(int j=0; j<n; j++)
            lx[i]=max(lx[i],x[i][j]);
    for(int i=0; i<n; i++)
    {
        while(1)
        {
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(dfspath(i))//找到路径
                break;
            int Min=INF+1;
            for(int j=0; j<n; j++) //扩大子图范围
            {
                if(visx[j])
                    for(int k=0; k<n; k++)
                        if(!visy[k])
                            Min=min(Min,lx[j]+ly[k]-x[j][k]);
            }
            for(int j=0; j<n; j++) //更新x,y点集标号
            {
                if(visx[j])
                    lx[j]-=Min;
                if(visy[j])
                    ly[j]+=Min;
            }
        }
    }
    ans=0;
    for(int i=0; i<n; i++) //计算权值和1
        ans+=x[dis[i]][i];
//        if(!flag)//求最小权值
//            ans=-ans;
    return ans;//返回权值
}
int main()
{
    while(~scanf("%d",&n))
    {
        //flag=1;//最大权匹配
        //flag=0;//最小权匹配 ,把权值取反然后求最大权匹配然后把结果取反
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                scanf("%d",&x[i][j]);
        //build_map();
        printf("%d\n",KM());
    }
}

优化后的:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=1e9;
int flag;
int x[500][500],n,lx[500],ly[500];
int visx[500],visy[500],dis[500],ans,slack[500],Min;
void build_map()//建图,单向图
{

}
int dfspath(int k)//匈牙利算法,寻找路径
{
    visx[k]=1;
    for(int i=0; i<n; i++)
    {
        if(visy[i])
            continue;
        int t=lx[k]+ly[i]-x[k][i];
        if(t==0)
        {
            visy[i]=1;
            if(dis[i]==-1||dfspath(dis[i]))
            {
                dis[i]=k;
                return 1;
            }
        }
        else
            //slack[i]=min(slack[i],t);//优化1
            Min=min(Min,t);//优化2
    }
    return 0;
}
int KM()
{
//    if(!flag)//最小权值处理
//    {
//        for(int i=0; i<n; i++)
//            for(int j=0; j<n; j++)
//                x[i][j]=-x[i][j];
//    }
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));//初始化y点集标号
    memset(dis,-1,sizeof(dis));//保存对应关系
    for(int i=0; i<n; i++) //初始化x点集标号
        for(int j=0; j<n; j++)
            lx[i]=max(lx[i],x[i][j]);
    for(int i=0; i<n; i++)
    {
//        for(int j=0;j<=n;j++)//优化1
//            slack[j]=INF;
        while(1)
        {
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            Min=INF+1;
            if(dfspath(i))//找到路径
                break;
//            for(int j=0; j<n; j++)//扩大子图范围  优化1 优化2不要这一步
//                if(!visy[j])
//                    Min=min(Min,slack[j]);
            for(int j=0; j<n; j++) //更新x点集标号
            {
                if(visx[j])
                    lx[j]-=Min;
                if(visy[j])
                    ly[j]+=Min;
//                else//有这一步会超时,但是有的人博客上有这一步,参考下
//                slack[i]-=Min;
            }
        }
    }
    ans=0;
    for(int i=0; i<n; i++) //计算权值和
        ans+=x[dis[i]][i];
//    if(!flag)//求最小权值
//        ans=-ans;
    return ans;//返回权值
}
int main()
{
    while(~scanf("%d",&n))
    {
        flag=1;
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                scanf("%d",&x[i][j]);
        printf("%d\n",KM());
    }
}
二分图最大匹配及最大权匹配(km算法) 看过很多二分图匹配的ppt,感觉就这个说的最清楚了,是一个叫刘汝佳的人写的,百度搜了一下貌似挺牛逼的,不管那么多,对km算法还抓耳挠腮的同志可以看看这个。 立即下载

相关推荐

指派问题—匈牙利算法.ppt

在生活中经常遇到这样的问题,某单位需完成n项任务,恰好有n个人可承担这些任务。由于每人的专长不同,各人完成任务不同(或所费时间),效率也不同。于是产生应指派哪个人去完成哪项任务,使完成n项任务的总效率最高(或所需总时间最小)。这问题称为指派问题或分派问题(Assignment problem)。

我对KM算法的理解

一般对KM算法的描述,基本上可以概括成以下几个步骤: (1) 初始化可行标杆 (2) 用匈牙利算法寻找完备匹配 (3) 若未找到完备匹配则修改可行标杆 (4) 重复(2)(3)直到找到相等子图的完备匹配 关于该算法的流程及实施,网上有很多介绍,基本上都是围绕可行标杆如何修改而进行的讨论,至于原理并没有给出深入的探讨。 KM算法是用于寻找带权二分图最佳匹配的算法。 二分图是...

茅屋 2812

制造业信息化的现实困局与未来展望:从基础到数字化的挑战与机遇

随着全球科技的发展和市场竞争的加剧,制造业的转型升级成为企业必须面临的挑战。在信息化和数字化的浪潮下,许多企业试图通过技术创新来提升自身竞争力。然而,现实情况是,绝大部分制造业企业的基本信息化都尚未完成,更遑论复杂的数字化。那么,制造业在信息化进程中面对哪些阻碍?未来又该如何实现从基础信息化到数字化的转型?

Yz2024的博客 2982

二分图带权最大匹配-KM算法详解

找不到对象就降低期望(

EQUINOX1的博客 6094

MIC(Maximal Information Coefficient)最大互信息系数

MIC(Maximal Information Coefficient)最大互信息系数是一种用于衡量两个变量之间相关性的统计量。它扩展了传统的互信息(MI)和条件互信息(CMI)的概念,具有更广泛的应用范围。MIC能够捕获包括功能性和非功能性的广泛的关联,具有普遍性和公平性。普遍性意味着在足够的样本量下,MIC能够捕捉到广泛的相关关系,而不仅仅局限于特定的功能类型;公平性则意味着MIC对不同类型的包含同等噪声的关系给出了相似的分数。需要注意的是,虽然MIC具有很多优点,但它也有一些局限性。

qlkaicx的博客 4603

手把手教你用UC3842搭建12V/5A反激电源(附PSIM仿真文件)

本文详细介绍了基于UC3842的12V/5A反激电源设计与PSIM仿真实践。从UC3842芯片选型、高频变压器计算到PSIM仿真模型搭建,提供完整的开关电源设计流程。特别包含PCB布局要点和实测优化建议,帮助工程师快速掌握反激电源开发技巧。

u6v7w8x的博客 1201

二分图匹配

二分图:设G=(V,{R})是一个无向图。如顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属两个不同的子集。则称图G为二分图。 匹配:给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。 最大匹配:匹配中边数最多的匹配。 完全匹配(完备匹配):如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,

智障 1601

银河麒麟V10新特性解析:从安装到AI应用的全面指南

本文全面解析银河麒麟V10操作系统的新特性,从安装指南到AI应用开发,详细介绍了其智能调度引擎、神经网络加速和场景化AI工具集等核心功能。通过实战案例展示如何高效配置AI环境、优化性能,并解决常见问题,助力开发者在国产操作系统上实现高效AI开发与应用部署。

seed的博客 299

二分图大合集——二分图最大匹配(最小覆盖数),完美匹配以及最优匹配(带权最大匹配)

二分图: 定义:二分图又称作二部图,是图论的一种特殊模型。设G=(V, E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A , B),且图中的每条边(i, j)所关联的两个定点分别属于这两个不同的顶点集(i in A, j in B),则称图G为一个二分图。 简单的说,一个图被分成了两部分,相同的部分没有边,那这个图就是二分图,二分图是特殊的图。(不含奇环) 由定义可知,二分图没有自...

ling_wang的博客 5万+

【保研经验】北科自动化到北大工学院

作者:办公室某学长 谢邀。。。作为拖延症晚期患者,希望能在我科开学前写完。 先简单介绍一下我的保研过程,申请了清华叉院&amp;北大叉院大数据&amp;北大信科计算机夏令营,三者都没入营;申请了自所夏令营(自所来宣讲时未交简历,这是重大错误),给了第二批补录但没去;最终九推去了北大工学院。我的这次保研最终成功的经历可以说有一定运气成分,不具有普适性,但在前期准备过程中还是有经验可以分享的。 ...

ruanjianbu的博客 1795

大学生作业:80C51存储器数据传输实验:基本指令和数据传送

大学生作业:80C51存储器数据传输实验,报价 200 文章目录实验一、80C51存储器数据传输实验实验目的:实验内容一:基本指令实验内容二:数据传送 实验一、80C51存储器数据传输实验 实验目的: 熟悉软件的集成开发环境 掌握单片机软件设计流程,掌握存储器结构及各窗口之间的联系 掌握内部数据存储器、外部数据存储器的数据传送特点和应用; 实验内容一:基本指令 用三种方法实现将累加器A内容改为20H ORG 0000H LJMP MAIN ORG 0030H MAIN: ;方法一使用寄

weixin_54707168的博客 5099

KM算法——带权二分图最佳匹配问题

【参考   我对KM算法的理解    http://philoscience.iteye.com/blog/1754498

DafeiACMer 2895

最详细的 SAP ABAP Web Service 创建和消费步骤讲解

本文原版发表于 SAP 官方社区,当时用的英文版写作,标题为:Step by step to create, consume and trace web service in ABAP system https://blogs.sap.com/2014/05/20/step-by-step-to-create-consume-and-trace-web-service-in-abap-system/ 总共阅读量超过 18 万。 How to create web service provider in A

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3148

带权二分图匹配-KM算法

1.KM算法基础 每个员工做不同的工作效率不同,如何分配使总效率最大? 暴力:用匈牙利算法求出所有最大匹配,再从中找出效率和最高的 KM算法:解决带权二分图最优匹配 2.KM算法流程 1.为各顶点赋值值,将左顶点赋值为最大权值,右顶点赋值为0 2.用匈牙利算法寻找完备匹配 3.若未找到完备匹配则修改顶点权值 4.重复(2)(3)直到找到完备匹配为止 时间复杂度O(n^3) 3.KM算法演示 (1...

Ogmx的博客 6753

Linux ARM平台开发系列讲解(摄像头V4L2子系统) 2.12.5 V4L2 control的原理和实现

既然涉及到视频输入,就会有很多与 相关的效果,比如对比度、饱和度、色温、白平衡等等,这些都是通用的、必须的控制项,并且大多数仅需要设置一个整数值即可。 内核中已经为我们提供了这个控制类型的,我们只需要明确自己需要添加什么控制类型,然后将其添加进内核中即可。该部分摄像头代码一半厂家会提供驱动或者相对应的参数,否则没有图像处理知识很难开发出来。 返回总目录...

DSMGUOGUO的博客 1435

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

二分图的最大匹配以及带权匹配【匈牙利算法+KM算法】

二分图算法包括 匈牙利算法 与 KM算法。 匈牙利算法 在这里写上模板。 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063 1 #include<stdio.h> 2 #include<string.h> 3 #define mem(a, b) memset(a, b, sizeof(...

a6334167的博客 859

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

二分图带权最佳匹配 KM算法

题目大意: 给定每一对男女之间的优势,求如何组合能让优势的总和最大。 算法描述: 首先可以看出来,这道题是一个带权的二分图匹配,KM算法的裸题。 这个博客写的很好 先来用自己的话简单的说一下。 读入数据之后,需要把我们记录的数组先求好,也就是 表示女与男之间的优势,这个先处理好就可以。 然后说算法的核心。首先,需要先知道二分图最大匹配。 可以理解为中介帮你介绍房子的问题。给定两个集合,它们之间有一些边相连,但两个集合内部没有边相连,求最多能两个集合之间连多少条边。 著名的匈......

glorious_dream的博客 1343

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

带权二分图的最佳匹配(KM算法)

还是没看懂一般图都是最大匹配问题。。怪我太笨了哎~ 先来个看明白了的KM算法——寻找带权二分图的最佳匹配方法 一般对KM算法的描述,基本上可以概括成以下几个步骤: (1) 初始化可行标杆 (2) 用匈牙利算法寻找完备匹配 (3) 若未找到完备匹配则修改可行标杆 (4) 重复(2)(3)直到找到相等子图的完备匹配 关于该算法的流程及实施,网上有很多介绍,基本上都是围绕可行标杆如何

x_y_q_的博客 2万+

KM算法学习 (二分图带权最大匹配)

计算 二分图带权最大匹配的2种方法: 费用流 / KM KM算法学习 使用局限性:只能在带权最大匹配是完备匹配的图中使用 完备匹配: G=<V1,V2,E>为二分图,∣V1∣<∣V2∣|V_1| < |V_2|∣V1​∣<∣V2​∣,MMM为GGG中的一个最大匹配数,且∣M∣=∣V1∣|M|= |V_1|∣M∣=∣V1​∣,则称MMM为V1V_1V1​到V2V_...

_llc的博客 456

Going Home(带权二分图最大匹配 KM算法)

原题: http://acm.hdu.edu.cn/showproblem.php?pid=1533 题意: 求所有m到各自不同的H的最小花费 解析: 在二分图基础上,边加权,寻找权值的最大匹配问题,可以用KM算法。这里的最小只需要改成相反数即可。 KM算法: 设M是一个带权完全二分图G的一个完备匹配,给每个顶点一个可行顶标(第i个x顶点的可行标用lx[i]表示,第j个y顶点的可行标用ly[j]表...

QAQ 735

hdu 2255 带权二分图最大匹配 KM算法

题意:现有n个村庄和n座房子,每个村庄分配一座房子。每个村庄分配的房子不同,则支付不同的金额。给出一个n*n矩阵,(i,j)坐标所在的数字表示第i个村庄买第j座房子需支付的价格。求分配房子可获得的最大价格。 题解:KM算法 1.带权二分图最大匹配直接用KM算法模板。 https://blog.youkuaiyun.com/chenshibo17/article/details/79933191 #i...

Irving0323的博客 525

HDU3722 Card Game KM算法的二分图带权匹配

Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=3722 【前言】 又搜刮来了一份代码。 用于求二分图的带权匹配。 记得以前看到过这道题,不够没什么思路。 昨天也是。 于是今天学了KM

Human_CK的专栏 776

二分图带权匹配的KM算法以及费用流建模

从理论上分析,KM算法的时间复杂度比费用流要好,但是实际上和较好的费用流算法比起来运行效率是差不多的,KM算法优势仅仅在于编程容易。而对于十分稀疏的图,许多优秀的费用流算法效率是很高的。这并不说明KM算法不如费用流,毕竟在ACM竞赛中,编程的复杂度也是一个相当重要的需要考虑的因素。

一点也不二 778

KM(Kuhn-Munkres)算法求带权二分图的最佳匹配

KM(Kuhn-Munkres)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的。但是,在了解了算法的执行过程和原理后,这些概念的意义和背后的作用就渐渐的显示出来了。因此,先暂时把相关概念列出来,看看,有个大概印象就好,等到了解了算法的流程后,在看原理中会有这些概念,那个时候回来细看就好了。 完备匹配:定义 ...

b10221001的博客 596

二分图带权匹配 KM算法与费用流模型建立

From: https://www.byvoid.com/blog/match-km/ [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和最大或最小。而二分图的最佳匹配则一定为完备匹配,在此基础上,才要求匹配的边权值之和最大或最小。二分图的带权匹配与最佳匹配不等价,也不互相包含。 我们可以使用KM算法实现求二分图的最

fyfcauc的专栏 741

HDU 2255:奔小康赚大钱(带权二分图最大匹配-KM算法)

HDU 2255:奔小康赚大钱(带权最大匹配-KM算法) 题目链接 题解: 题目解释已经很裸了,就是带权的二分图最大匹配。 以前也一直都没接触KM算法,一直拖到了现在。。。。。 虽然看有些视频也讲KM算法其实用的的不多,而且完全可以用最大流来解决,但是还是想着先了解了解原理,把模板熟悉熟悉 参考的这篇博客的代码: https://www.cnblogs.com/wenruo/p/5264235.h...

serendipity的博客 443
上一篇: 线段树
下一篇: 最小费用流
acmer_zp
博客等级 码龄11年 18粉丝 110原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值