匈牙利算法

匈牙利算法

问题简介

设G=(V,E)是一个无向图。如顶点集V可分割为两个互不相交的子集V1,V2之并,并且图中每条边依附的两个顶点都分属于这两个不同的子集。则称图G为二分图。二分图也可记为G=(V1,V2,E)。

给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。

选择这样的子集中边数最大的子集称为图的最大匹配问题(maximal matching problem)

如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备,完美匹配。

算法描述

求最大匹配的一种显而易见的算法是:先找出全部匹配,然后保留匹配数最多的。但是这个算法的时间复杂度为边数的指数级函数。因此,需要寻求一种更加高效的算法。下面介绍用增广路求最大匹配的方法(称作匈牙利算法,匈牙利数学家Edmonds于1965年提出)。

增广路的定义(也称增广轨或交错轨):

若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。 由增广路的定义可以推出下述三个结论:

1-P的路径长度必定为奇数,第一条边和最后一条边都不属于M。 2-将M和P进行异或操作(去同存异)可以得到一个更大的匹配M’。 3-M为G的最大匹配当且仅当不存在M的增广路径。 算法轮廓:

(1)置M为空

(2)找出一条增广路径P,通过异或操作获得更大的匹配M’代替M

(3)重复(2)操作直到找不出增广路径为止

时间空间复杂度

时间复杂度 邻接矩阵:最坏为O(n^3) 邻接表:O(mn)

空间复杂度 邻接矩阵:O(n^2) 邻接表:O(m+n)

样例程序

格式说明

输入格式:

第1行3个整数,V1,V2的节点数目n1,n2,G的边数m

第2-m+1行,每行两个整数t1,t2,代表V1中编号为t1的点和V2中编号为t2的点之间有边相连

输出格式:

1个整数ans,代表最大匹配数

邻接矩阵-C

#include

#include

int n1, n2, m, ans;

int result[101]; //记录V2中的点匹配的点的编号

bool state [101]; //记录V2中的每个点是否被搜索过

bool data[101][101];//邻接矩阵 true代表有边相连

void init()

{

int t1, t2;

memset(data, 0, sizeof(data));

memset(result, 0, sizeof(result));

ans = 0;

scanf(

for (int i = 1; i

{

scanf(

data[t1][t2] = true;

}

return;

}

bool find(int a)

{

for (int i = 1; i

{

if (data[a][i] == 1 && !state[i]) //如果节点i与a相邻并且未被查找过 {

state[i] = true; //标记i为已查找过

if (result[i] == 0 //如果i未在前一个匹配M中

|| find(result[i])) //i在匹配M中,但是从与i相邻的节点出发可以有增广路 {

result[i] = a; //记录查找成功记录

return true; //返回查找成功

}

}

}

return false;

}

int main()

{

init();

for (int i = 1; i

{

memset(state, 0, sizeof(state)); //清空上次搜索时的标记

if (find(i)) ans++; //从节点i尝试扩展

}

printf(

return 0;

}

邻接表-C++

#include

#include

using namespace std;

//定义链表

struct link

{

int data; //存放数据

link* next; //指向下一个节点

link(int=0);

};

link::link(int n)

{

data=n;

next=NULL;

}

int n1,n2,m,ans=0;

int result[101]; //记录n1中的点匹配的点的编号

bool state [101]; //记录n1中的每个点是否被搜索过

link *head [101]; //记录n2中的点的邻接节点

link *last [101]; //邻接表的终止位置记录

//判断能否找到从节点n开始的增广路

bool find(const int n)

{

link* t=head[n];

while (t!=NULL) //n仍有未查找的邻接节点时

{

if (!(state[t->data])) //如果邻接点t->data未被查找过

{

state[t->data]=true; //标记t->data为已经被找过

if ((result[t->data]==0) || //如果t->data不属于前一个匹配M

(find(result[t->data]))) //如果t->data匹配到的节点可以寻找到增广路 {

result[t->data]=n; //那么可以更新匹配M',其中n1中的点t->data匹配n return true; //返回匹配成功的标志

}

}

t=t->next; //继续查找下一个n的邻接节点

}

return false;

}

int main()

{

int t1=0, t2=0;

cin>>n1>>n2>>m;

for (int i=0; i

{

cin>>t1>>t2;

if (last[t1]==NULL)

last[t1]=head[t1]

=new link(t2);

else

last[t1]=last[t1]->next

=new link(t2);

}

for (int i=1; i

memset(state, 0, sizeof(state)); if (find(i)) ans++;

}

cout

return 0;

}


相关文章

  • 浅析指派问题的匈牙利解法成稿
  • 浅析指派问题的匈牙利解法 胡小芹 数学科学学院 数学与应用数学 学号:040414057 指导教师:苏孟龙 摘要:对于指派问题,可以利用许多理论进行建模并加以解决,但匈牙利解法是解决指派问题的一种非常简单有效的方法,并且可以解决多种形式的指派问题,但匈牙利算法本身存在着一些问题,本文主要介绍了匈牙利 ...

  • 运筹学重要考点
  • 运筹学重要考点 第一部分:线性规划 1.线性规划与单纯形法 (1)线性规划问题的数学模型 (2)线性规划问题解的概念 (3)线性规划问题的图解法 (4)单纯形法 ①将所给问题标准化 ②计算.迭代步骤 ③最优性的判定(解的判定定理) ④人工变量法:大M 法和两阶段法 2.对偶问题 ⑴原问题转化为对应的 ...

  • 图论及其应用
  • <图论及其应用>课程建设探索 徐 俊 明 摘 要 本文叙述了图论的飞速发展和它的广泛应用, 在高等理工院校中开设<图论及其应用>课程对深化教学改革, 更新教学内容, 优化学生的知识结构, 培养跨世纪人才的必要性和重要性.同时结合作者开设此课程的多年教学实践, 介绍对该课程进行 ...

  • veilog 语言书写规范
  • 2.5.1 信号命名规则 信号命名规则在团队开发中占据着重要地位,统一.有序的命名能大幅减少设计人员之间的冗余工作,还可便于团队成员代码的查错和验证.比较著名的信号命名规则当推Microsoft 公司的"匈牙利"法,该命名规则的主要思想是"在变量和函数名中加入前缀以增进 ...

  • 运筹学考试大纲
  • 运筹学考试大纲 一.考试方法和考试时间 本课程为笔试闭卷考试.考试时间为2小时 二.考试的基本要求 学生通过学习该课程,应了解运筹学对优化决策问题进行定量研究的特点,理解线性规划.多目标规划.整数规划.动态规划.图与网络等分支的基本优化原理,掌握其中常用的模型和算法,具备一定的建模能力. 三.考试内 ...

  • 运筹学整数规划补例
  • 运筹学难点辅导材料 整数规划补例 max z =x 1+x 2 ⎧14x 1+9x 2≤51⎪-6x +3x ≤1 1.对(IP )整数规划问题,问用先解相应的线性规划然后凑整的办法能否⎪12 s .. t ⎨ ⎪x 1≥0, x 2≥0⎪⎩x 1, x 2为整数 求到最优整数解?再用分支定界法求解 ...

  • 基于FPGA的阵列乘法器的设计与实现
  • 基于FPGA 的阵列乘法器的设计与实现 本文先对乘法器进行了分析,然后用现场可编程门阵列(FPGA)实现了阵列乘法器,并分析了设计原理. 0 引言 乘法是运算中的基本算法,应用也最为广泛.在计算机中乘法最基本的操作就是移位相加,各类乘法最终都要归结为这一点.早期计算机中为了简化硬件结构,采用串行的移 ...

  • 配送作业管理第四章流通加工职业活动教学设计.
  • 流通加工职业活动教学设计单元名称 单元 简介流通加工基本认知学时4本单元主要介绍流通加工的一些基本内容,包括流通加工基本流程.流通加工与生产加工的区别.不同流通加工的类型.地位和作用.形 式和特点.匈牙利方法.不合理流通加工的表现形式等. 能力 目标1. 能举例说明生活中典型的流通加工案例,并阐述通 ...

  • 面试java高级工程师.项目经理等的常见问题
  • 1. 类.对象的概念: 1) 类:具有共同属性和行为的对象的抽象.类是创建对象的模板. 2) 对象:现实世界中的实体.在计算机中,是指可标识的存储区域. 3) 类是对象的抽象.对象是类的实例. 2. 抽象:是从特定的实例中抽取共同性质形成一般化概念的过程. 3. 接口与抽象类: 1)接口和抽象类都用 ...

  • 程序的书写规则(程序的编码规范)
  • 程序的书写规则(程序的编码规范) 随着软件产品的功能增加和版本的提高,代码越来越复杂,源文件也越来越多,对于软件开发人员来说,除了保证程序运行的正确性和提高代码的运行效率之外,规范风格的编码会对软件的升级.修改.维护带来极大的方便性,也保证程序员不会陷入"代码泥潭"中无法自拔.开 ...

© 2024 范文中心 | 联系我们 webmaster# onjobs.com.cn