二分图

二分图 最大权匹配 km算法

瘦欲@ 提交于 2020-02-06 02:48:15
这个算法的本质还是不断的找增广路; KM算法的正确性基于以下定理: 若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。 这个定理是显然的。因为对于二分图的任意一个匹配,如果它包含于相等子图,那么它的边权和等于所有顶点的顶标和;如果它有的边不包含于相等子图,那么它的边权和小于所有顶点的顶标和。所以相等子图的完备匹配一定是二分图的最大权匹配。 (1)可行点标:每个点有一个标号,记lx[i]为X方点i的标号,ly[j]为Y方点j的标号。如果对于图中的任意边(i, j, W)都有lx[i]+ly[j]>=W,则这一组点标是 可行 的。特别地,对于lx[i]+ly[j]=W的边(i, j, W),称为 可行边 ; (2)KM算法的核心思想就是通过修改某些点的标号(但要满足点标始终是可行的),不断增加图中的可行边总数,直到图中存在仅由可行边组成的完全匹配为止,此时这个匹配一定是最佳的(因为由可行点标的的定义,图中的任意一个完全匹配,其边权总和均不大于所有点的标号之和,而仅由可行边组成的完全匹配的边权总和等于所有点的标号之和,故这个匹配是最佳的)。一开始,求出每个点的初始标号:lx[i]=max{e.W|e.x=i}(即每个X方点的初始标号为与这个X方点相关联的权值最大的边的权值),ly[j]=0

KM算法 详解+模板 出自http://blog.sina.com.cn/s/blog_691ce2b701016reh.html

寵の児 提交于 2020-02-06 02:46:24
先说KM算法求二分图的最佳匹配思想,再详讲KM的实现。 【KM算法求二分图的最佳匹配思想】 对于具有二部划分( V1, V2 )的加权完全二分图,其中 V1= { x1, x2, x3, ... , xn }, V2= { y1, y2, y3, ... , yn },边< xi, yj >具有权值 W i,j 。 该带权二分图中一个总权值最大的完美匹配,称之为最佳匹配。 记 L(x) 表示结点 x 的标记量,如果对于二部图中的任何边<x,y>,都有 L(x)+ L(y)>= W x,y ,我们称 L 为二部图的可行顶标。 设 G(V,E) 为二部图, G'(V,E') 为二部图的子图。如果对于 G' 中的任何边<x,y> 满足, L(x)+ L(y)== W x,y ,我们称 G'(V,E') 为 G(V,E) 的等价子图。 定理一:设 L 是二部图 G 的可行顶标。若 L 等价子图 G L 有完美匹配 M,则 M 是 G 的最佳匹配。 证明:由于 G L 是 G 的等价子图,M 是 G L 的完美匹配,所以,M 也是 G 的完美匹配。以由于对于匹配 M 的每条边 e ,都有 e∈ E( G L ),而且 M 中每条边覆盖每个顶点正好一次,所以 W( M )= å W(e), e∈ M = å L(x), x∈ V 另一方面,对于 G 的任何完美匹配 M' 有 W( M' )=

【网络流24题】 方格取数问题

别来无恙 提交于 2020-02-03 11:52:47
题目描述 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。 输入格式 第 1 行有 2 个正整数 m 和 n,分别表示棋盘的行数和列数。接下来的 m 行,每行有 n 个正整数,表示棋盘方格中的数。 输出格式 程序运行结束时,将取数的最大总和输出 输入输出样例 输入 #1 3 3 1 2 3 3 2 3 2 3 1 输出 #1 11 分析 如果将棋盘黑白染色,黑点放左边,白点放右边,每个黑点向相邻的白点连边,会形成一个二分图。 然后每个点都有点权,我们要选择一些点,这些点之间没有边,使得点权最大。 这是二分图的最大独立集问题,就是选出一些点集,每条边至多选择一个点,使得点权和最大。 和它对立的是二分图的最小覆盖集问题,就是选出一些点集,每条边至少选一个点,使得点权和最小。 显然 最大独立集 = V - 最小覆盖集 我们试着求最小覆盖集问题。 建一个超级源点 s s s 和超级汇点 t t t ,从 s s s 到黑点连边,容量为权值, 白点到 t t t 连边,容量为权值,黑点到白点连容量为 i n f inf i n f 的边,求最小割,即是最小覆盖集。如图。 为什么最小割就是答案? 由于中间的边是 i n f

二分图——机器任务(最小点覆盖)

你说的曾经没有我的故事 提交于 2020-02-02 01:24:46
机器任务 有两台机器 A,B 以及 K 个任务。 机器 A 有 N 种不同的模式(模式0~N-1),机器 B 有 M 种不同的模式(模式0~M-1)。 两台机器最开始都处于模式0。 每个任务既可以在A上执行,也可以在B上执行。 对于每个任务 i,给定两个整数 a[i] 和 b[i],表示如果该任务在 A 上执行,需要设置模式为 a[i],如果在 B 上执行,需要模式为 b[i]。 任务可以以任意顺序被执行,但每台机器转换一次模式就要重启一次。 求怎样分配任务并合理安排顺序,能使机器重启次数最少。 输入格式 输入包含多组测试数据。 每组数据第一行包含三个整数 N, M, K。 接下来k行,每行三个整数 i, a[i]和b[i],i 为任务编号,从0开始。 当输入一行为0时,表示输入终止。 输出格式 每组数据输出一个整数,表示所需的机器最少重启次数,每个结果占一行。 数据范围 N , M < 100 , K < 1000 N,M<100,K<1000 N , M < 1 0 0 , K < 1 0 0 0 0 ≤ a [ i ] < N 0≤a[i]<N 0 ≤ a [ i ] < N 0 ≤ b [ i ] < M 0≤b[i]<M 0 ≤ b [ i ] < M 输入样例: 5 5 10 0 1 1 1 1 2 2 1 3 3 1 4 4 2 1 5 2 2 6 2 3 7 2 4

染色法判断二分图

吃可爱长大的小学妹 提交于 2020-01-28 17:06:09
二分图:不存在奇数环也就是相邻两个点颜色不同就是二分图 给定一个n个点m条边的无向图,图中可能存在重边和自环。 请你判断这个图是否是二分图。 输入格式 第一行包含两个整数n和m。 接下来m行,每行包含两个整数u和v,表示点u和点v之间存在一条边。 输出格式 如果给定图是二分图,则输出“Yes”,否则输出“No”。 数据范围 1 ≤ n , m ≤ 10 5 1≤n,m≤105 输入样例: 4 4 1 3 1 4 2 3 2 4 输出样例: Yes############################################################## 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1e5+10, M = 2*1e5+10; 5 int h[N], e[M], ne[M], idx; 6 int color[N];//0 无色 1 2 各代表一种color 7 int n, m; 8 9 void add(int a, int b){ 10 e[idx] = b, ne[idx] = h[a], h[a] = idx ++; 11 } 12 13 bool dfs(int u, int c){ 14 color[u] = c; 15 for(int i = h

二分图多重匹配

萝らか妹 提交于 2020-01-26 18:17:11
二分图多重匹配 一般的二分图匹配与多重匹配之间的区别就是: 二分图多重匹配:右边的物品可以和多个左边的相匹配,同时右边的物品可以有一个最大匹配容量V[i] int cnt [ maxn ] , V [ maxn ] ; //cnt[i]记录现在第i个星球有多少个人,V[i]记录i星球的容量 int linker [ maxn ] [ 15 ] ; //linker[i][j]表示第i个星球第j个匹配的人是谁 bool dfs ( int u ) { for ( int i = 1 ; i <= m ; i ++ ) { if ( mapp [ u ] [ i ] && ! vis [ i ] ) //表示第u个人可以匹配第i个星球 { vis [ i ] = 1 ; if ( cnt [ i ] < V [ i ] ) //并且该星球人数未上限,直接匹配 { linker [ i ] [ cnt [ i ] ++ ] = u ; return true ; } for ( int j = 0 ; j < V [ i ] ; j ++ ) { if ( dfs ( linker [ i ] [ j ] ) ) //可以让位置 { linker [ i ] [ j ] = u ; return true ; } } } } return false ; } bool solve ( )

网络流学习笔记

瘦欲@ 提交于 2020-01-25 16:49:10
网络流学习笔记 简介网络流 网络流应该是NOIP考纲范围内一个比较难的知识点,其实用心学习还是觉得比较简单。 这里用最通俗的语言讲一讲我认识中的网络流,显然是一个初步的概念。 解决网络流问题总是变成这样一个模型: 想象你现在面前有一个城市的排水系统,是由一个个单向联通的管道组成的,其中有一个节点S可以源源不断的流出水,另一个节点T可以源源不断的吸收水, 除此之外其他节点只能流入和流出水,不能排入或者排出水,而管道的粗细是一定的,每根管道在同一时间只能流入一个上限的流量c,现在让你对这个网络进行分析。 1. 求这个网络的S节点(源点)可以在同一时刻流出水的最大流量 2. 若每个管道有一个输送费用(单位流量的花费),求第1问的若干方案里面,保证最大流量基础上,最小代价是多少 3. 若每个管道有一个输送价值(单位流量的价值),求第1问的若干方案里面,保证最大流量基础上,最大价值是多少 这里我们会用最通熟易懂的语言讲述这三个常规问题的做法。 流量网络的分析(最简单的概念) 引入一个概念 流量网络 ,什么是流量网络,就是给你的原始的流量图只有每条边的限流而具体的最大可行的流量未知 引入一个概念 可行流量 ,我们定义一个函数f(u,v)这个由一个二元组映射到一个值表示一条边(u,v)∈E 的可行流量。 引入一个概念 限流量 ,c(u,v)表示一条边(u,v)∈E,由于一些限制最多能流经的流量

二分图最大匹配

醉酒当歌 提交于 2020-01-24 14:20:24
二分图是图,可以用图的数据结构存储二分图,邻接矩阵和邻接表 二分图的特点是,图的顶点可以分为两组,两组组内的节点之间没有连接,所有的连接都是在两组之间的。 所谓一个匹配是两组节点一对一的连接。 二分图的最大匹配所要完成的一个任务是在一个二分图中找出最多的匹配数。 二分图最大匹配匈牙利算法的核心在于新增加的一对匹配能否成功的加入到结果集当中去。 能够成功加入分为两种情况 情况1.右侧的节点还没有连接 情况2.如果右侧的节点已经连接,通过调整右侧节点连接的左节点,将右侧节点空出来。(这是一个递归的过程) 为什么在为左边的每一个顶点匹配是都要重置数组? 防止上一轮的遍历对当前造成影响。实际上标记vis数组的过程就是情况2的调整过程。 每一轮的调整都是独立的。 代码模板 hdu2063 /* 匈牙利算法解决二分图最大匹配问题 采用的邻接矩阵的形式,g[i][j] maxn代表一边最多的顶点数,un代表左边顶点数,vn代表右边顶点数 linked[i]代表右边的第i个点与左边哪个点相匹配 */ #include <iostream> #include <stdio.h> #include <algorithm> #include <string.h> using namespace std; const int maxn=502; int un,vn; //左边顶点数,右边顶点数 int g

二分图匹配

拟墨画扇 提交于 2020-01-24 14:09:22
   这两个星期一直没什么时间上机,最近学了学二分图,这里就来记录一下。 ------------------------------------------------------------分割线   先讲讲一些基本概念:   二分图:在一个图中,如果图中的点可以被分为两个部分,两部分之间有若干条边相连,且每个部分的点之间无边相连,则该图是一个二分图。由此可以很容易知道,二分图绝对是一个无环图。   匹配:图论中,一个“匹配”是一个边的集合,其中任意两条都没有公共定点。由此衍生出一些其他的概念,匹配点,匹配边,未匹配点,未匹配边,定义显而易见就不多赘述了。   最大匹配:一个二分图中包含的边数最大的一个匹配就是这个二分图的最大匹配。一般二分图的问题经常会涉及到最大匹配,所以这也是学习二分图的一个重点。   完美匹配:如果在一个二分图中,存在一个匹配使得所有点都是匹配点,则这个匹配称为这个二分图的完美匹配。可知,一个二分图的完美匹配一定也是这个二分图的一个最大匹配。      如上图,图一是一个二分图,但从外表并不明显,可以转换成图二的样式。图三是这个二分图的一个匹配(红线部分),图四则是它的最大匹配,也是完美匹配。   讲完基本概念,来说说解决二分图最大匹配的常用算法——匈牙利算法。   首先讲讲两个概念,交替路和增广路。   如右图   交替路: 从一个未匹配点出发

二分图的匹配(未完)

我的未来我决定 提交于 2020-01-24 14:08:36
  二分图是一种特殊类型的图,图中的顶点集被划分成X与Y两个子集,图中每条边的两个端点,一定是一个属于X另一个属于Y。二分图的匹配是求边的一个子集,该子集中的任意两条边都没有公共的端点。含边数最多的匹配即为二分图的最大匹配;如果给二分图的边加权,则边权和最大的匹配即为最佳匹配。   如果可以以某种方式将研究的对象分成两个互补的集合,而需要求得他们之间满足某种条件的“一一对应”关系时,往往可以抽象出对象以及对象之间的关系,构造二分图,然后利用匹配算法来解决。构造二分图模型,设计匹配算法,并对其算法进行适当的优化。   另外二分图的覆盖数=匹配数,所以求最小覆盖,可以转化为求最大匹配。其证明比较繁琐,组合数学的书上有。 1. 采用网络流的方法计算二分图的最大匹配   将二分图该做成一个网络:增加一个源点 s 、一个汇点 t ,由s到X集合中每点增加一条边,由Y中每点到t增加一条边。   复杂度分析:找到一条增广路径的时间约为O(n*e),最多n次寻找,时间复杂度为O(e*n^2) 2. 计算二分图最大匹配的匈牙利算法   匈牙利算法是通过构造一颗交错树来计算二分图的最大匹配的。不断的加入增广路径。   代码: #define MAXV 200int N, M; //X和Y顶点数分别为N、Mbool mt[MAXV][MAXV];//二分图, 邻接矩阵bool used[MAXV]; /