二分图最大匹配问题(贪心算法)
运筹学匈牙利法
运筹学匈牙利法运筹学匈牙利法(Hungarian Algorithm),也叫匈牙利算法,是解决二部图最大(小)权完美匹配(也称作二分图最大权匹配、二分图最小点覆盖)问题的经典算法,是由匈牙利数学家Kuhn和Harold W. Kuhn发明的,属于贪心算法的一种。
问题描述在一个二分图中,每个节点分别属于两个特定集合。
找到一种匹配,使得所有内部的节点对都有连边,并且找到一种匹配方案,使得该方案的边权和最大。
应用场景匈牙利算法的应用场景较为广泛,比如在生产调度、货车调度、学生对导师的指定、电影的推荐等领域内,都有广泛的应用。
算法流程匈牙利算法的伪代码描述如下:进行循环ɑ、选择一点未匹配的点a作为起点,它在二分图的左边β、找出a所有未匹配的点作为下一层节点ɣ、对下一层的每个节点,如果它在右边未匹配,直接匹配ɛ、如果遇到一个已经匹配的节点,进入下一圈,考虑和它匹配的情况δ、对已经匹配的点,将它已经匹配的点拿出来,作为下一层节点,标记这个点作为已被搜索过ε、将这个点作为当前层的虚拟点,没人配它,看能否为它找到和它匹配的点ζ、如果能匹配到它的伴侣,令它们成对被匹配最后输出最大权匹配。
算法优缺点优点:相比于暴力求解二分图最大权匹配来说,匈牙利算法具有优秀的解决效率和高效的时间复杂度,可以在多项式时间(O(n^3))内解决二分图最大权匹配问题。
缺点:当二分图较大时,匈牙利算法还是有很大的计算复杂度,复杂度不佳,算法有效性差。
此时就需要改进算法或者使用其他算法。
总结匈牙利算法是一个常见的解决二分图最大权匹配问题的算法,由于其简洁、易用、效率优秀等特性,广泛应用于学术和实际问题中。
匈牙利算法虽然在处理较大规模问题时效率不佳,但仍然是一种值得掌握的经典算法。
离散数学中的的匹配与覆盖问题
离散数学中的的匹配与覆盖问题在离散数学中的匹配与覆盖问题,我们研究的是如何在给定的集合中,找到满足特定条件的组合或者子集。
匹配与覆盖问题在实际生活中有着广泛的应用,例如在社交网络中匹配好友,组织中分配任务,以及物流中优化路径等等。
1. 匹配问题匹配问题是指在一个给定的图中,找到一个子图,使得子图的边集中的每个顶点都只有一条边与之关联。
在离散数学中,匹配问题可以表示为一个图的问题,其中图的顶点表示对象,边表示对象之间的关系。
在旅行商问题中,我们经常使用匹配来解决路线规划问题。
在一个包含多个城市的地图中,我们可以通过匹配算法找到最短的路径,从而使得旅行商能够尽快地访问到每个城市。
2. 覆盖问题覆盖问题是指从给定的集合中选取一些元素,使得这些元素能够覆盖其他元素的集合。
在离散数学中,覆盖问题可以表示为一个集合系统,并且需要找到一个最小的子集,使得它覆盖了集合系统中的所有元素。
在电信领域,我们经常会遇到覆盖问题。
例如,在一个城市中建设无线信号基站,我们需要在有限的基站数量下,选择合适的位置,使得基站能够覆盖到尽可能多的用户。
通过覆盖问题的研究,我们可以优化基站的布局,提高网络的覆盖率。
3. 匹配与覆盖问题的解决方法在离散数学中,匹配与覆盖问题有着丰富的解决方法。
其中一种常见的方法是图论中的匈牙利算法,它可以用于解决二分图的最大匹配问题。
匈牙利算法的基本思想是通过增加路径来找到当前路径的增广路径,并最终找到最大匹配。
另外一种常见的解决方法是贪心算法,它可以用于解决覆盖问题。
贪心算法的基本思想是每次选择一个局部最优的解决方案,并逐步构建全局最优解。
通过不断地选择覆盖集合中最多未被覆盖的元素,贪心算法可以找到一种近似的最优解。
此外,还有其他一些算法和方法可以用于解决匹配与覆盖问题,如线性规划、网络流等。
根据问题的具体要求和限制条件,选择合适的算法和方法进行求解。
思考匹配与覆盖问题给我们带来的启示,我们发现离散数学在实际问题中有着广泛的应用。
ACM算法总结
(1)几何公式.
(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)
(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)
(poj1408,poj1584)
(4)最小树形图(poj3164)
(5)次小生成树.
(6)无向图、有向图的最小环
三.数据结构.
(1)trie图的建立和应用. (poj2778)
(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和 在线算法
(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)
(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)
五.动态规划
(1)背包问题. (poj1837,poj1276)
(2)型如下表的简单DP(可参考lrj的书 page149):
(4)凸包. (poj2187,poj1113)
中级:
一.基本算法:
(1)C++的标准模版库的应用. (poj3096,poj3007)
(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)
二.图算法:
(3)记忆化搜索(poj3373,poj1691)
五.动态规划
(1)较为复杂的动态规划(如动态规划解特别的施行商问题等)
(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)
(2)四边形不等式理论.
程序设计竞赛常用算法
程序设计竞赛常用算法1.排序算法:排序是一个基本的算法问题,常见的排序算法有冒泡排序、选择排序、插入排序、快速排序、归并排序等。
这些排序算法有各自的优势和适用场景,需要根据具体问题需求选择合适的算法。
2.图论算法:图论是程序设计竞赛中经常出现的重要领域。
常见的图论算法有深度优先(DFS)、广度优先(BFS)、Dijkstra算法、Floyd-Warshall算法、拓扑排序、最小生成树等。
这些算法可以用于解决最短路径、连通性、最大流最小割等问题。
3.动态规划:动态规划是一种常用于解决优化问题的算法。
该算法通过将问题分解成子问题,并记录子问题的解来求解原问题的最优解。
常见的动态规划算法有背包问题、最长公共子序列(LCS)、最大子序列和等。
4.字符串处理算法:字符串处理是程序设计竞赛中常见的问题。
常见的字符串处理算法有KMP算法、哈希算法、字符串匹配等。
这些算法可以用于解决模式匹配、字符串、字符统计等问题。
5.数学算法:数学算法在程序设计竞赛中也经常被使用。
常见的数学算法有质因数分解、素数筛、快速乘法、高精度计算等。
这些算法可以用于解决数论、计算几何、概率等问题。
6.图形算法:图形算法主要用于处理图像和几何图形。
常见的图形算法有扫描线算法、凸包算法、几何运算等。
这些算法可以用于解决图像处理、三维建模等问题。
7.树和图的遍历算法:树和图的遍历算法是程序设计竞赛中常用的算法之一、常见的树和图的遍历算法有先序遍历、中序遍历、后序遍历、深度优先(DFS)、广度优先(BFS)等。
这些算法可以用于解决树和图的构建、路径等问题。
8.最大匹配和最小割算法:最大匹配算法用于求解二分图的最大匹配问题,常见的算法有匈牙利算法。
最小割算法用于求解图的最小割问题,常见的算法有Ford-Fulkerson算法。
这些算法可以用于解决网络流和二分图匹配等问题。
9.贪心算法:贪心算法是一种常用于优化问题的算法。
该算法通过每一步选择局部最优解来达到全局最优解。
POJ 题目整理
初期:一.基本算法:(1)枚举. (poj1753,poj2965)(2)贪心(poj1328,poj2109,poj2586)(3)递归和分治法.(4)递推.(5)构造法.(poj3295)(6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法:(1)图的深度优先遍历和广度优先遍历.(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)(3)最小生成树算法(prim,kruskal) (poj1789,poj2485,poj1258,poj3026)(4)拓扑排序 (poj1094)(5)二分图的最大匹配 (匈牙利算法) (poj3041,poj3020)(6)最大流的增广路算法(KM算法). (poj1459,poj3436)三.数据结构.(1)串 (poj1035,poj3080,poj1936)(2)排序(快排、归并排(与逆序数有关)、堆排) (poj2388,poj2299)(3)简单并查集的应用.(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)(5)哈夫曼树(poj3253)(6)堆(7)trie树(静态建树、动态建树) (poj2513)四.简单搜索(1)深度优先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)五.动态规划(1)背包问题. (poj1837,poj1276)(2)型如下表的简单DP(可参考lrj的书 page149):1.E[j]=opt{D+w(i,j)} (poj3267,poj1836,poj1260,poj2533)2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最长公共子序列) (poj3176,poj1080,poj1159)3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)六.数学(1)组合数学:1.加法原理和乘法原理.2.排列组合.3.递推关系.(POJ3252,poj1850,poj1019,poj1942)(2)数论.1.素数与整除问题2.进制位.3.同余模运算.(poj2635, poj3292,poj1845,poj2115)(3)计算方法.1.二分法求解单调函数相关知识.(poj3273,poj3258,poj1905,poj3122)七.计算几何学.(1)几何公式.(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)(poj1408,poj1584)(4)凸包. (poj2187,poj1113)中级:一.基本算法:(1)C++的标准模版库的应用. (poj3096,poj3007)(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)二.图算法:(1)差分约束系统的建立和求解. (poj1201,poj2983)(2)最小费用最大流(poj2516,poj2516,poj2195)(3)双连通分量(poj2942)(4)强连通分支及其缩点.(poj2186)(5)图的割边和割点(poj3352)(6)最小割模型、网络流规约(poj3308, )三.数据结构.(1)线段树. (poj2528,poj2828,poj2777,poj2886,poj2750)(2)静态二叉检索树. (poj2482,poj2352)(3)树状树组(poj1195,poj3321)(4)RMQ. (poj3264,poj3368)(5)并查集的高级应用. (poj1703,2492)(6)KMP算法. (poj1961,poj2406)四.搜索(1)最优化剪枝和可行性剪枝(2)搜索的技巧和优化 (poj3411,poj1724)(3)记忆化搜索(poj3373,poj1691)五.动态规划(1)较为复杂的动态规划(如动态规划解特别的施行商问题等) (poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)(2)记录状态的动态规划. (POJ3254,poj2411,poj1185)(3)树型动态规划(poj2057,poj1947,poj2486,poj3140)六.数学(1)组合数学:1.容斥原理.2.抽屉原理.3.置换群与Polya定理(poj1286,poj2409,poj3270,poj1026).4.递推关系和母函数.(2)数学.1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)2.概率问题. (poj3071,poj3440)3.GCD、扩展的欧几里德(中国剩余定理) (poj3101)(3)计算方法.1.0/1分数规划. (poj2976)2.三分法求解单峰(单谷)的极值.3.矩阵法(poj3150,poj3422,poj3070)4.迭代逼近(poj3301)(4)随机化算法(poj3318,poj2454)(5)杂题. (poj1870,poj3296,poj3286,poj1095)七.计算几何学.(1)坐标离散化.(2)扫描线算法(例如求矩形的面积和周长并,常和线段树或堆一起使用).(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)(3)多边形的内核(半平面交)(poj3130,poj3335)(4)几何工具的综合应用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)高级:一.基本算法要求:(1)代码快速写成,精简但不失风格(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)(2)保证正确性和高效性. poj3434二.图算法:(1)度限制最小生成树和第K最短路. (poj1639)(2)最短路,最小生成树,二分图,最大流问题的相关理论(主要是模型建立和求解) (poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446) (3)最优比率生成树. (poj2728)(4)最小树形图(poj3164)(5)次小生成树.(6)无向图、有向图的最小环三.数据结构.(1)trie图的建立和应用. (poj2778)(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和在线算法(RMQ+dfs)).(poj1330)(3)双端队列和它的应用(维护一个单调的队列,常常在动态规划中起到优化状态转移的目的).(poj2823)(4)左偏树(可合并堆).(5)后缀树(非常有用的数据结构,也是赛区考题的热点). (poj3415,poj3294)四.搜索(1)较麻烦的搜索题目训练(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)(2)广搜的状态优化:利用M进制数存储状态、转化为串用hash表判重、按位压缩存储状态、双向广搜、A*算法. (poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)(3)深搜的优化:尽量用位运算、一定要加剪枝、函数参数尽可能少、层数不易过大、可以考虑双向搜索或者是轮换搜索、IDA*算法.(poj3131,poj2870,poj2286)五.动态规划(1)需要用数据结构优化的动态规划. (poj2754,poj3378,poj3017)(2)四边形不等式理论.(3)较难的状态DP(poj3133)六.数学(1)组合数学.1.MoBius反演(poj2888,poj2154)2.偏序关系理论.(2)博奕论.1.极大极小过程(poj3317,poj1085)2.Nim问题.七.计算几何学.(1)半平面求交(poj3384,poj2540)(2)可视图的建立(poj2966)(3)点集最小圆覆盖.(4)对踵点(poj2079)八.综合题.(poj3109,poj1478,poj1462,poj2729,poj2048,poj3336,poj3315,poj2148,poj1263) 以及补充Dp状态设计与方程总结1.不完全状态记录<1>青蛙过河问题<2>利用区间dp2.背包类问题<1> 0-1背包,经典问题<2>无限背包,经典问题<3>判定性背包问题<4>带附属关系的背包问题<5> + -1背包问题<6>双背包求最优值<7>构造三角形问题<8>带上下界限制的背包问题(012背包)3.线性的动态规划问题<1>积木游戏问题<2>决斗(判定性问题)<3>圆的最大多边形问题<4>统计单词个数问题<5>棋盘分割<6>日程安排问题<7>最小逼近问题(求出两数之比最接近某数/两数之和等于某数等等)<8>方块消除游戏(某区间可以连续消去求最大效益)<9>资源分配问题<10>数字三角形问题<11>漂亮的打印<12>邮局问题与构造答案<13>最高积木问题<14>两段连续和最大<15>2次幂和问题<16>N个数的最大M段子段和<17>交叉最大数问题4.判定性问题的dp(如判定整除、判定可达性等)<1>模K问题的dp<2>特殊的模K问题,求最大(最小)模K的数<3>变换数问题5.单调性优化的动态规划<1>1-SUM问题<2>2-SUM问题<3>序列划分问题(单调队列优化)6.剖分问题(多边形剖分/石子合并/圆的剖分/乘积最大)<1>凸多边形的三角剖分问题<2>乘积最大问题<3>多边形游戏(多边形边上是操作符,顶点有权值)<4>石子合并(N^3/N^2/NLogN各种优化)7.贪心的动态规划<1>最优装载问题<2>部分背包问题<3>乘船问题<4>贪心策略<5>双机调度问题Johnson算法8.状态dp<1>牛仔射击问题(博弈类)<2>哈密顿路径的状态dp<3>两支点天平平衡问题<4>一个有向图的最接近二部图9.树型dp<1>完美服务器问题(每个节点有3种状态)<2>小胖守皇宫问题<3>网络收费问题<4>树中漫游问题<5>树上的博弈<6>树的最大独立集问题<7>树的最大平衡值问题<8>构造树的最小环转一个搞ACM需要的掌握的算法.要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来.适合自己的才是好的,有的人不适合搞算法,喜欢系统架构,因此不要看到别人什么就眼红, 发挥自己的长处,这才是重要的.第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打出来.1.最短路(Floyd、Dijstra,BellmanFord)2.最小生成树(先写个prim,kruscal要用并查集,不好写)3.大数(高精度)加减乘除4.二分查找. (代码可在五行以内)5.叉乘、判线段相交、然后写个凸包.6.BFS、DFS,同时熟练hash表(要熟,要灵活,代码要简)7.数学上的有:辗转相除(两行内),线段交点、多角形面积公式.8. 调用系统的qsort, 技巧很多,慢慢掌握.9. 任意进制间的转换第二阶段:练习复杂一点,但也较常用的算法。
贪心算法通过每次选择局部最优解来达到全局最优
贪心算法通过每次选择局部最优解来达到全局最优贪心算法是一种常用的解决优化问题的算法。
它通过每次选择局部最优解来达到全局最优的目标。
在本文中,我们将介绍贪心算法的原理、应用场景以及优缺点。
一、原理贪心算法的基本原理非常简单:每一步都选择当前状态下的局部最优解,最终得到的结果就是全局最优解。
贪心算法不考虑过去的选择对未来的影响,只关注眼前的最佳选择。
二、应用场景贪心算法在各个领域都有广泛的应用,下面我们将以几个常见的实际问题来说明。
1. 图的最小生成树问题在一个连通无向图中,找到一个包含所有节点且权值最小的无回路子图,这个问题称为最小生成树问题。
贪心算法可以通过每次选择权值最小的边来逐步构建最小生成树。
2. 分糖果问题有一组孩子和一组糖果,每个孩子有一个需求因子和每个糖果有一个大小。
当糖果的大小不小于孩子的需求因子时,孩子可以获得该糖果。
目标是尽可能多地满足孩子的需求,贪心算法可以通过给每个孩子分配满足其需求因子的最小糖果来达到最优解。
3. 区间调度问题给定一个任务列表,每个任务有一个开始时间和结束时间。
目标是安排任务的执行顺序,使得尽可能多的任务能够被完成。
贪心算法可以通过选择结束时间最早的任务来实现最优解。
以上只是一些贪心算法的应用场景,实际上贪心算法可以用于解决各种优化问题。
三、优缺点1. 优点①简单:贪心算法的思路相对简单,容易理解和实现。
②高效:由于只考虑局部最优解,贪心算法的时间复杂度较低,通常能够在较短的时间内得到一个接近最优解的结果。
③可用于近似求解:由于贪心算法不保证得到全局最优解,但可以用于求解近似最优解的问题。
2. 缺点①不保证全局最优解:贪心算法只考虑眼前的最优选择,无法回溯和修正过去的选择,因此不能保证得到全局最优解。
②局部最优解无法转移:在某些情况下,局部最优解并不一定能够转移到全局最优解,导致贪心算法得到的结果偏离最优解。
③对问题的要求较高:由于贪心算法需要找到适合的局部最优解,因此问题必须具备一定的特殊性,而一些问题无法使用贪心算法解决。
《算法设计与分析》课程实验报告 (贪心算法(一))
《算法设计与分析》课程实验报告实验序号:07实验项目名称:实验8 贪心算法(一)一、实验题目1.删数问题问题描述:键盘输入一个高精度的正整数N(不超过250 位),去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的非负整数。
编程对给定的N 和k,寻找一种方案使得剩下的数字组成的新数最小。
若输出前有0则舍去2.区间覆盖问题问题描述:设x1,x2,...xn是实轴上的n个点。
用固定长度为k的闭区间覆盖n个点,至少需要多少个这样的固定长度的闭区间?请你设计一个有效的算法解决此问题。
3.会场安排问题问题描述:假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。
设计一个有效的贪心算法进行安排。
(这个问题实际上是著名的图着色问题。
若将每一个活动作为图的一个顶点,不相容活动间用边相连。
使相邻顶点着有不同颜色的最小着色数,相应于要找的最小会场数。
)4.导弹拦截问题问题描述:某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。
但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
某天,雷达捕捉到敌国的导弹来袭。
由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
给定导弹依次飞来的高度(雷达给出的高度数据是≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
二、实验目的(1)通过实现算法,进一步体会具体问题中的贪心选择性质,从而加强对贪心算法找最优解步骤的理解。
(2)掌握通过迭代求最优的程序实现技巧。
(3)体会将具体问题的原始数据预处理后(特别是以某种次序排序后),常能用贪心求最优解的解决问题方法。
三、实验要求(1)写出题1的最优子结构性质、贪心选择性质及相应的子问题。
(2)给出题1的贪心选择性质的证明。
(3)(选做题):写出你的算法的贪心选择性质及相应的子问题,并描述算法思想。
frégier定理证明及推广
Frégier定理证明及推广Frégier定理证明及推广Frégier定理是图论中的一个重要结论,它提供了关于二分图的一个重要性质。
本文将分别介绍Frégier定理的证明方法、定理推广、应用领域以及相关定理。
●定理证明方法Frégier定理的证明方法基于贪心算法和数学归纳法。
以下是具体的证明步骤:●初始化:令$G$为待处理的二分图,$A$和$B$分别为图的两个子集。
选择一个节点$x$,将其放入$A$中。
●贪心策略:对于每个未处理的节点$y$,如果$y$与$A$中的节点相邻接,则将$y$放入$B$中;否则将$y$放入$A$中。
●数学归纳法:假设经过k轮处理后,已经将节点$x_1, x_2, \ldots, x k$分别放入了$A$和$B$中。
对于第k+1个节点$x{k+1}$,根据贪心策略进行处理。
在证明过程中,需要证明经过贪心策略处理后,得到的二分图是平衡的,即两个子集的节点数量相差不超过1。
为了证明这一点,可以使用数学归纳法,通过对节点数目的归纳来逐步推导。
●定理推广Frégier定理的推广主要集中在两个方面:一是将定理应用于更广泛的图类,二是寻找更高效的算法实现。
在应用范围方面,Frégier定理的结论可以扩展到一般图论中的平衡二分问题。
例如,对于一个给定的图,可以尝试使用Frégier算法将其分成两个平衡的子图。
此外,还可以将平衡二分的概念推广到超图上,研究超图的平衡二分问题。
在算法优化方面,贪心策略的核心是将每个节点放入与其相邻接的节点较少的子集中。
这一策略可以在实际应用中进行优化,例如使用优先队列等数据结构来加速查找相邻节点的过程。
此外,还可以研究使用启发式算法来改进Frégier算法的性能,例如使用模拟退火等优化方法来避免局部最优解。
●应用领域Frégier定理的应用领域广泛,主要包括以下几方面:●社交网络分析:社交网络中的用户可以抽象为图的节点,用户之间的互动关系可以抽象为边的连接。
二分图最大匹配及常用建图方法
算法———艺术二分图匹配剖析很多人说,算法是一种艺术。
但是对于初学者的我,对算法认识不是很深刻,但偶尔也能感受到他强大的魅力与活力。
这让我追求算法的脚步不能停止。
下面我通过分析匈牙利算法以及常用建图方式,与大家一起欣赏算法的美。
匈牙利算法匈牙利算法是用来解决最大二分图匹配问题的,所谓二分图即“一组点集可以分为两部分,且每部分内各点互不相连,两部分的点之间可以有边”。
所谓最大二分图匹配即”对于二分图的所有边,寻找一个子集,这个子集满足两个条件,1:任意两条边都不依赖于同一个点。
2:让这个子集里的边在满足条件一的情况下尽量多。
首先可以想到的是,我们可以通过搜索,找出所有的这样的满足上面条件的边集,然后从所有的边集中选出边数最多的那个集合,但是我们可以感觉到这个算法的时间复杂度是边数的指数级函数,因此我们有必要寻找更加高效的方法。
目前比较有效的方法有匈牙利算法和通过添加汇点和源点的网络流算法,对于点的个数都在200 到300 之间的数据,我们是采取匈牙利算法的,因为匈牙利算法实现起来要比网络流简单些。
下面具体说说匈牙利算法:介绍匈牙利之前,先说说“增广轨”。
定义:若P是图G中一条连通两个未匹配顶点的路径,并且属最大匹配边集M的边和不属M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广轨定义总是抽象的下面通过图来理解它。
图中的线段(2->3, 3->1, 1->4)便是上面所说的p路径,我们假定边(1,3)是以匹配的边,(2,3)(1,4)是未匹配的边,则边(4,1)边(1,3)和边(3,2)在路径p上交替的出现啦,那么p就是相对于M的一条增广轨,这样我们就可以用边1,4 和边2,3来替换边1,3 那么以匹配的边集数量就可以加1,。
匈牙利算法就是同过不断的寻找增广轨实现的。
很明显如果二分图的两部分点分别为n 和m,那么最大匹配的数目应该小于等于MIN(n,m); 因此我们可以枚举任第一部分(的二部分也可以)里的每一个点,我们从每个点出发寻找增广轨,最后吧第一部分的点找完以后,就找到了最大匹配的数目,当然我们也可以通过记录找出这些边。
Python中的贪心算法
Python中的贪心算法贪心算法是一种简单而有效的算法,通常用于对最优解进行近似求解。
它通过不断地做出最合适的选择来达到全局最优解的近似,而不是对整个问题进行全面的评估。
贪心算法的核心思想是:在每一步中都选择当前最优的解决方案,然后再尝试将其与其他已选择的解决方案组合起来,得到更优的解决方案。
这种方法通常很容易实现,并且可以得到符合实际使用的结果。
但是,贪心算法并不总是能够得到全局最优解,有时会出现选择局部最优解而导致全局最优解无法实现的情况。
贪心算法的应用范围非常广泛,它可用于优化问题、图形问题、字符串问题等各种领域,并且还可以与其他算法组合使用。
例如,贪心算法可以与动态规划算法结合使用,以加快计算速度并得到更好的结果。
贪心算法通常有以下几个基本步骤:1.确定问题的最优子结构贪心算法的第一步是确定问题是否具有最优子结构。
它意味着,在问题的任何阶段,我们都可以通过选择当前最优的子问题解决方案来获得最优解决方案。
这样,我们就可以逐步地将问题分解为更小、更容易处理的子问题。
2.确定问题的贪心选择性质贪心算法的第二步是确定问题的贪心选择性质。
它意味着我们必须找到一种方法来使每一步的贪心选择都是局部最优的,并且能够达到全局最优解。
这通常需要我们对问题进行更深入的分析,以找到那些能够获得最高收益的解决方案。
3.构造整体最优解贪心算法的最后一步是使用贪心选择性质,逐步构造全局最优解。
这意味着我们在每一步中都要做出当前最优的选择,并将其添加到我们的解决方案中,直到得到整个问题的最优解。
下面我们将简单介绍一下贪心算法在不同领域的应用。
【1】组合优化问题在组合优化问题中,贪心算法通常用于通过寻找不断优化的局部解决方案来构建更好的全局解决方案。
例如,在背包问题中,我们要选择一些物品放入背包中,以使得它们的总重量不超过背包的容量,同时价值最高。
使用贪心算法,我们可以按照物品的价值密度(即物品的价值与重量之比)进行排序,然后选择具有最高价值密度的物品,以使得我们可以尽可能地放入更多的物品,并尽可能地增加总价值。
最优装载问题(贪心)
最优装载问题(贪⼼)⼀、实验内容运⽤贪⼼算法解决活动安排问题(或最优装载问题)使⽤贪⼼算法解决最优装载问题。
⼆、所⽤算法基本思想及复杂度分析1.算法基本思想贪⼼算法是指在对问题求解时,总是做出在当前看来是最好的选择。
也就是说,不从整体最优上加以考虑,它所做出的仅是在某种意义上的局部最优解。
⽤局部解构造全局解,即从问题的某⼀个初始解逐步逼近给定的⽬标,以尽可能快的求得更好的解。
当某个算法中的某⼀步不能再继续前进时,算法停⽌。
2.问题分析及算法设计问题分析:(1)给定n个古董,要把它们装到装载量为c的装载船上。
(2)⾸先需要对这n个古董进⾏质量从⼩到⼤的排序。
(3)然后每次都选择最轻的,接着再从剩下的n-1件物品中选择最轻的。
(4)重复第(3)步骤,直到当前载重量⼤于装载船的最⼤装载量,停⽌装载。
(5)此时得到最优的贪⼼⽅案,记录下装载的最⼤古董数。
算法设计:(1)算法策略:把n件物品从⼩到⼤排序,然后根据贪⼼策略尽可能多的选出前i个物品,直到不能装为⽌。
(2)特例:算法复杂度分析由最优装载问题的贪⼼选择性质和最优⼦结构性质,可知将这些古董按照其重量从⼩到⼤排序,所以算法所需的计算时间为O(nlogn)。
三、源程序核⼼代码及注释(截图)四、运⾏结果五、调试和运⾏程序过程中产⽣的问题及解决⽅法,实验总结(5⾏以上)这⾥的调试,没有什么⼤问题,单纯的依次⽐较,判断,从⽽得到结果。
这次实验让我对贪⼼算法有了更深刻的认识,其主要是从问题的初始解出发,按照当前最佳的选择,把问题归纳为更⼩的相似的⼦问题,并使⼦问题最优,再由⼦问题来推导出全局最优解。
贪⼼算法虽然求的是局部最优解,但往往许多问题的整体最优解都是通过⼀系列的局部最优解的选择来达到的,所以贪⼼算法不⼀定可以得到能推导出问题的最优解,但其解法是最优解的近似解。
懂得算法的原理,还需要多去练习才能更好的掌握其⽤法。
源码:#include<iostream>#include<algorithm>#define MAXN 1000005using namespace std;int w[MAXN];//每件古董的重量int main(){int c,n;//c:载重量,n古董数int sum = 0;//装⼊古董的数量int tmp = 0;//装⼊古董的重量cin >> c >> n;for(int i= 1; i <= n; ++i)cin >> w[i];sort(w+1,w+1+n);for(int i = 1; i <= n; ++i){tmp += w[i];if(tmp <= c)++sum;elsebreak;}cout << sum << endl;return 0;}。
算法常见解题思路
算法解题可以采用许多不同的思路和方法,以下是一些常见的解题思路:
1. 贪心算法(Greedy Algorithm):每一步都选择当前情况下看起来最优的选择,以期望最终获得全局最优解。
2. 动态规划(Dynamic Programming):将复杂问题分解为较小的子问题,并借助已解决的子问题的结果来解决更大的问题,通常使用记忆化搜索或者自底向上的迭代方法。
3. 分治算法(Divide and Conquer):将问题划分为两个或多个相对简单的子问题,分别求解,然后将子问题的解合并以得到原问题的解。
4. 回溯算法(Backtracking):通过穷举所有可能的解,并逐步构建可行解,当发现当前解不能满足要求时,回退选择继续尝试其他路径。
5. 搜索算法:根据问题的性质,采用广度优先搜索(BFS)或深度优先搜索(DFS)等搜索策略来遍历问题的解空间,寻找满足条件的解。
6. 排序和查找算法:根据问题的特点,选择合适的排序算法(如快速排序、归并排序、堆排序等)或查找算法(如二分查找、哈希查找等)来解决问题。
7. 图算法:根据问题的图结构特点,采用广度优先搜索(BFS)、深度优先搜索(DFS)、最短路径算法(Dijkstra、Floyd-Warshall)、最小生成树算法(Prim、Kruskal)等图算法来解决问题。
8. 数学模型和优化算法:将问题转化为数学模型,并采用数学方法或优化算法(如线性规划、整数规划、贪心算法、遗传算法等)来求解。
以上仅为一些常见的解题思路,选择合适的算法思路需要根据问题的特点和复杂度进行综合分析和评估。
对于复杂的问题,常常需要结合多种思路和方法来解决,以达到更好的解题效果。
信息学竞赛常用算法
信息学竞赛常用算法一、贪心算法(Greedy Algorithm)贪心算法是一种简单而直观的算法,它的核心思想是每一步都选择最优解,希望最终的结果也能最优。
贪心算法常常用于求解最小生成树、最短路径、背包问题等。
例如,在最小生成树问题中,贪心算法可以根据边的权重选择最小的边,直到生成树包含所有节点。
二、动态规划(Dynamic Programming)动态规划是一种通过将问题分解为子问题,并存储子问题的解来解决复杂问题的方法。
它常常用于求解最长公共子序列、最大子数组和、背包问题等。
动态规划的核心思想是,通过计算和存储子问题的解,避免重复计算,从而提高算法的效率。
三、深度优先(Depth First Search)深度优先是一种用于遍历或图或树的算法,其核心思想是尽可能深入地一个分支,直到无法继续为止,然后回溯到上一个节点,继续其他分支。
深度优先可以用于求解拓扑排序、连通分量、可达性等问题。
四、广度优先(Breadth First Search)广度优先是一种用于遍历或图或树的算法,其核心思想是从根节点开始,依次与当前节点相邻的节点,直到找到目标节点为止。
广度优先可以用于求解最短路径、连通性、迷宫问题等。
五、并查集(Union Find)并查集是一种用于管理元素间的等价关系的数据结构。
并查集主要包括两个操作:查找和合并。
查找操作用于确定元素所属的集合,合并操作用于将两个元素所属的不同集合合并为一个集合。
并查集常常用于求解连通性问题、最小生成树问题等。
六、最小生成树(Minimum Spanning Tree)最小生成树是一种用于连接一个连通图的所有节点,并且边的权重之和最小的树形结构。
最小生成树算法主要包括Prim算法和Kruskal算法。
Prim算法是一种贪心算法,通过选择最小权重的边进行扩展,直到生成树包含所有节点。
Kruskal算法通过不断添加权重最小的边,直到生成树包含所有节点。
七、最短路径(Shortest Path)最短路径是一种从起点到终点的路径中,总权重最小的路径。
【计算机】十大经典算法
第一版
1
搜索算法 一、 算法描述:
下面以 n 皇后问题为样例讲解 将 n 个皇后摆放在一个 n x n 的棋盘上,使得每一个皇后都无法攻击到其他皇 后。 深度优先搜索 (DFS) 显而易见, 最直接的方法就是把皇后一个一个地摆放在棋盘上的合法位置上,枚 举所有可能寻找可行解。可以发现在棋盘上的每一行(或列)都存在且仅存在一 个皇后,所以,在递归的每一步中,只需要在当前行(或列)中寻找合法格,选 择其中一个格摆放一个皇后。
简表:
d :解的深度 k :搜索树的深度 d <= k
记住每一种搜索法的优势。 如果要求求出最接近根节点的解, 则使用 BFD 或 ID。 而如果是其他的情况,DFS 是一种很好的搜索方式。如果没有足够的时间搜出所 有解。那么使用的方法应最容易搜出可行解,如果答案可能离根节点较近,那么 就应该用 BFS 或 ID,相反,如果答案离根节点较远,那么使用 DFS 较好。还有, 请仔细小心空间的限制。 如果空间不足以让你使用 BFS, 那么请使用迭代加深吧!
3
样例:骑士覆盖问题[经典问题]
在一个 n x n 的棋盘中摆放尽量少的骑士,使得棋盘的每一格都会被至少一个 骑士攻击到。但骑士无法攻击到它自己站的位置. 广度优先搜索 (BFS) 在这里, 最好的方法莫过于先确定 k 个骑士能否实现后再尝试 k+1 个骑士,这 就叫广度优先搜索。通常,广度优先搜索需用队列来帮助实现。
truncated_dfsearch(i+1, remove knight
复杂度:
ID 时间复杂度与 DFS 的时间复杂度(O(n))不同,另一方面,它要更复杂,某 次 DFS 若限界 k 层,则耗时 ck 。若搜索树共有 d 层,则一个完整的 DFS-ID 将耗时 c0 + c1 + c2 + ... + cd 。如果 c = 2 ,那么式子的和是 cd+1 - 1 , 大约是同效 BFS 的两倍。当 c > 2 时(子节点的数目大于 2),差距将变小: ID 的时间消耗不可能大于同效 BFS 的两倍。 所以,但数据较大时,ID-DFS 并不 比 BFS 慢,但是空间复杂度却与 DFS 相同,比 BFS 小得多。
03贪心算法
第3章贪心算法贪心算法一般来说是解决“最优问题”,具有编程简单、运行效率高、空间复杂度低等特点。
是程序竞赛中的一个有力武器,受到广大同学们的青睐。
贪心算法一般是求“最优解”这类问题的。
最优解问题可描述为:有n个输入,它的解是由这n个输入的某个子集组成,并且这个子集必须满足事先给定的条件。
这个条件称为约束条件。
而把满足约束条件的子集称为该问题的可行解。
这些可行解可能有多个。
为了衡量可行解的优劣,事先给了一个关于可行解的函数,称为目标函数。
目标函数最大(或最小)的可行解,称为最优解。
贪心算法的正确性证明虽然不容易,但一些常见的方法还是值得总结的。
1.构造法根据描述的算法,用贪心的策略,依次构造出一个解,可证明一定是合法的解。
即用贪心法找可行解。
2.反证法用贪心的策略,依次构造出一个解S1。
假设最优解S2不同与S1,可以证明是矛盾的。
从而S1就是最优解。
3.调整法用贪心的策略,依次构造出一个解S1。
假设最优解S2不同与S1,找出不同之处,在不破坏最优性的前提下,逐步调整S2,最终使其变为S1。
从而S1也是最优解。
3.1 构造法构造法就是从一个空的解开始,根据贪心策略,逐步将新的内容加入原有的解中,直到满足要求或无法将新的元素加入为止。
也可以将使用相反的手段,即先将整个解设定为一个最大的集合,然后,用贪心策略逐步从原有解中取出元素,直至满足要求或无法取出元素为止。
本节例题将介绍第一种贪心的例子。
3.1.1 〖案例1〗订票一家票务办公室为音乐会售票。
它们以出售某一固定数量的连号票(简称套票)来替代常见的单张票销售。
票务办收到了大量的购票订单。
套票的订单以该套票中最小的座位号作为标识。
然而票务办并不能满足所有的订单,而且如果他们完全按照观众的要求来分·60· ACM 程序设计培训教程配座位,就会出现很多空位。
为此票务办采取了如下的座位分配和价格策略:如果一个订单被接受且完全按照观众的要求安排座位,那么观众就要付全价(每套票2 petaks);如果一个订单虽被接受但是至少有一个座位与观众的要求不同,那么顾客只需付半价(每套票1 petaks)。
《图论课件第五章匹配与因子分解》课件
二、因子分解
2.1 定义
因子分解是将图进行拆分,使得每个因子都是图的 一个子图。
2.2 贪心算法
贪心算法用于在因子分解时选择边或顶点。
2.3 DAG上的匈牙利算法
用于在有向无环图上寻找因子分解的算法。
2.4 Tutte定理
用于判断一个图是否存在完美匹配。
三、应用实例
1
3.1 二分图最大匹配的应用
《图论课件第五章匹配与 因子分解》PPT课件
图论课件第五章匹配与因子分解
一、匹配
1.1 定义
匹配指的是图中的一组边,这些边不相交并且 没有公共顶点。
1.3 最大匹配
最大匹配是图中包含边数最多的匹配。
1.2 匹配的分类
分类包括完美匹配、最大匹配和最小匹配。
1.4 匈牙利算法
匈牙利算法用于寻找二分图的最大匹配。
应用于任务分配、婚姻匹配等场景。
3.2 带权二分图匹配的应用
2
应用于资源分配、工作调度等场景。
3
3.3 双倍经验的关卡通关问题
使用匹配算法解决游戏中的关卡设计问
3.4 理发店问题
4
题。
利用匹配算法解决顾客理发需要和理发 师时间安排的问题。
四、参考资料
4.1 书籍
《图论导论》、《算法导论》等
4.3 网站
Grap h Alg orithm s, Grap h Theo ry Online等
4.2 论文
Graph Matching Alg orithm s: A C om prehensive C om parison
4.4 其他资源
相关研究报告、课程讲义等
配第——克拉克定理
配第——克拉克定理配第——克拉克定理,是一种在计算机科学领域应用广泛的算法定理,可以用来判断无向图是否为二分图。
下面我们将分步骤来介绍这一定理的具体内容。
第一步,了解二分图首先,我们需要了解什么是二分图。
简单来说,二分图是指图中的所有顶点可以被分为两个不相交的子集,每个子集中的顶点之间没有边相连。
在实际应用中,二分图常常被用来表示一些具有互斥关系的问题,比如集合覆盖问题、染色问题等等。
第二步,理解配第算法接下来,我们需要理解配第算法。
配第算法,也称为匈牙利算法,是一种用来解决二分图匹配问题的算法。
在一个二分图中,我们需要找到一个子图,使其所有顶点都能够匹配到另一个子图的顶点。
为了实现这一目的,配第算法采用了一种贪心的思想。
具体来说,该算法从图中任选一个顶点(比如A),然后搜索与之相邻的点,如果找到了一个没有被匹配过的顶点(比如B),就将A和B匹配起来,并标记B 为已匹配。
接着,再找到图中与B相邻但未匹配的点,并将二者匹配起来。
如此循环查找直到无法再匹配为止。
第三步,介绍克拉克定理克拉克定理,也称为配第——克拉克定理,是判断一个无向图是否为二分图的定理。
克拉克定理的核心思想是:如果一个无向图中的每个点的度数都不超过二分图中最大的独立集大小(即子图中每个顶点都没有与自己相邻的点),那么它就是一个二分图。
这个定理的证明跟配第算法有关,通过一系列的推理可以证明,如果一个无向图不是二分图,那么存在一个奇环,且这个奇环大小不小于三。
接着,通过把奇环上的点分为两个集合,即黑白两个集合,就可以得到一个二分图。
第四步,实现配第——克拉克定理最后,我们需要介绍如何实现配第——克拉克定理。
实际上,这个定理的实现非常简单,只需要遍历图中的每个顶点,检查它的度数是否都不超过最大独立集的大小即可。
如果发现某个顶点的度数大于最大独立集的大小,那么这个图就不是一个二分图。
以上就是关于配第——克拉克定理的介绍,这个定理在计算机科学领域应用广泛,有着重要的理论和实际价值。
算法设计与分析论文(贪心算法)
贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪 心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划 算法的主要区别。
贪心选择是采用从顶向下、以迭代的方法做出相继选择,每做一次贪心选择 就将所求问题简化为一个规模更小的子问题。对于一个具体问题,要确定它是否 具有贪心选择的性质,我们必须证明每一步所作的贪心选择最终能得到问题的最 优解。通常可以首先证明问题的一个整体最优解,是从贪心选择开始的,而且作 了贪心选择后,原问题简化为一个规模更小的类似子问题。然后,用数学归纳法 证明,通过每一步贪心选择,最终可得到问题的一个整体最优解。
物品超出背包容量为止。伪代码如下:
public static void DepWePr(double[][] a, double c, int[] ans) { // depend on
// the // weight // and price double[] w = new double[a[0].length]; // the weight of goods System.arraycopy(a[0], 0, w, 0, w.length); // copy the array
贪心算法
——不在贪心中爆发,就在贪心中灭亡 徐晓龙 武汉理工大学计算机科学与技术学院软件 ZY1101 班
摘要
本文介绍贪心算法的基本意义以及算法的使用范围,并通过具体的案例来分 析贪心算法的具体应用,从而指出其特点和存在问题。 关键字:贪心算法,贪心策略,TSP、0/1 背包
引言
我们用了 13 周的时间学完了《算法设计与分析》这本书。这本书中涵盖了 大量的常见算法,包括蛮力法、分治法、动态规划法、贪心算法等等。我最有印 象的就是贪心算法。贪心算法是一种有合理的数据组织和清晰高效的算法,它简 单有效。下面我们来详细解读一下这个算法。
贪心算法
顾名思义,贪心算法总是作出在当前看来最好的选择。
也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。
当然,希望贪心算法得到的最终结果也是整体最优的。
虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。
如单源最短路经问题,最小生成树问题等。
在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。
活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子。
该问题要求高效地安排一系列争用某一公共资源的活动。
贪心算法提供了一个简单、漂亮的方法使得尽可能多的活动能兼容地使用公共资源。
设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。
每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi 。
如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。
若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。
也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。
template<class Type>void GreedySelector(int n, Type s[], Type f[], bool A[]){A[1]=true;int j=1;for (int i=2;i<=n;i++) {if (s[i]>=f[j]) { A[i]=true; j=i; }else A[i]=false;}}由于输入的活动以其完成时间的非减序排列,所以算法greedySelector每次总是选择具有最早完成时间的相容活动加入集合A中。
直观上,按这种方法选择相容活动为未安排活动留下尽可能多的时间。
也就是说,该算法的贪心选择的意义是使剩余的可安排时间段极大化,以便安排尽可能多的相容活动。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
注意
以上所述的贪心算法仅适用于二分图的最 大匹配问题,最佳匹配问题是不适用的。 本人尚未见到有人能够对此算法给出严格 的证明,但是网上确实也有不少人有用此 算法过全点的经历。 总之,请各位慎重使用! (:以下附例题的主程序的代码
主程序代码
procedure add(i,j:longint); begin inc(top); v[top]:=j; next[top]:=u[i]; u[i]:=top; inc(degree[i]); end; procedure ins(i:longint); var o:longint; begin visit[i]:=true; inc(tot); o:=u[i]; while o<>0 do begin dec(degree[v[o]]); o:=next[o]; end; end; begin readln(n,m,k); for a:=1 to k do begin readln(b,c); c:=n+c; add(b,c); add(c,b); end;
网络流算法(编程复杂,小题大做) 匈牙利算法(理解困难,实现简单) 以上这些我都不会怎么办?
贪心算法
下面,我们引进一种能够完美解决二分图 最大匹配问题的贪心算法。
会议安排
一个重要的会议由A公司的M位代表和B公司的N 位代表参加(M,N≤1000,代表用1,2,……, M和1,2,……,N表示)。他们被预先分成 K(K≤60000)组进行谈判。每组两个人分别来自A 公司和B公司。每个参加会议的代表都至少参加 了一组谈判。会议为每一个代表都准备了一个房 间。技术人员将会在一些房间之间连上直通电话, 一个代表至少要和他的一个谈判对手直接联络。 连接一个直通电话的价格是常数。技术人员要用 尽量少的花费满足会议的要求。
贪心算法
接着,我们将u,v两点都进行删除操作。 (当u的出边所对的点都已被访问,那么就找 不到满足条件的v,因此只对u进行操作) 所谓删除操作,在这里,删除s,其实就是 将s的所有出边所对的点t的出度都减一。 (因为要删除点s,即(s,t)也被删除,即(t,s) 也要被删除,所以t的出度要减一)
二分图最大匹配问题 (贪心算法) 贪心算法)
BY 长郡中学 曹博凯
二分图的基本概念
二分图是一类特殊的图结构 二分图是这样一种图:G的顶点集合V分成 两部分X与Y,G中每条边的两个端点一定 是一个属于X而另一个属于Y。
匹配的基本概念
设G=[V,E]是一个无向图,M属于E是G的 若干条边的集合,如果M中的任意两条边Biblioteka 没有公共的端点,就称M是一个匹配。
题目分析
这道题目我们很容易将其抽象成为二分图 最大匹配的基本模型。我们可以用匈牙利 算法求出其最大匹配M,然后所求解即为 n+m-M。 可是,考场上并不是每个人都能想到这一 巧妙的转换。 于是,我们可以怀抱着一种骗分的心态, 构造出一种贪心策略,从而得到满分!
贪心算法
首先,我们将每条无向边拆分成两条反向 的有向边,存储在邻接表中。与此同时, 我们记录下每个顶点的出度。 然后,我们每次找出一个当前未被访问过 的结点中,出度最小的结点u。同时,再在 以该结点u为起始点的所有边所对的点中, 找出一个同样满足未被访问,且出度最小 的结点v。
主程序代码
n:=n+m; while tot<n do begin b:=maxlongint;//找结点u for a:=1 to n do if(not visit[a])and(degree[a]<b)then begin b:=degree[a]; c:=a; end; a:=u[c]; b:=maxlongint;// b:=maxlongint;//找结点v v while a<>0 do begin if(not visit[v[a]])and(degree[v[a]]<b)then begin b:=degree[v[a]]; d:=v[a]; end; a:=next[a]; end; inc(ans);//连边,答案加一 ins(c);//对u进行删除操作 if b<>maxlongint then ins(d);//如果存在v,对v进行删除操作 end; writeln(ans);; end.
贪心算法
这样循环做下来,我们每做一次都相当于 连了一条边(u,v),于是inc(ans)。 同时,我们对这条边的两个端点u,v都做了 删除操作(如果可以的话)。每删一个点 就inc(tot),直到tot=n+m,即两边的点均被 删完。 此时我们得到的ans值即为答案,直接输出 即可。
总结
以上就是简单明了的二分图最大匹配的贪 心算法。 比起前面所提到的网络流算法和匈牙利算 法,都有着无可比拟的优越性。 它不但比前面两个算法都要好理解,而且 不及网络流算法的编程复杂度,也不用担 心匈牙利算法的递归层数。
最大匹配的基本概念
从给定的图G=[V,E]的所有匹配中,把包 含边数最多的匹配找出来。这种匹配即所 谓的最大匹配问题。
二分图的最大匹配
e.g.飞行员分成两部分,一部分是正驾驶员, 一部分是副驾驶员。显然,如何搭配正副 驾驶员才能使出航飞机最多的问题可以归 结为一个二分图上的最大匹配问题。
常用算法