二分图常见问题总结

算法讲解:二分图匹配 二分图匹配,自然要先从定义入手,那么二分图是什么呢? 二分图: 二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。 简单的说,一个图被分成了两部分,相同的部分没有边,那这个图就是二分图,二 阅读详情

1.二分图

二分图是指一个图能够分成两部分,每一部分的点之间互相没有连边
比如说这个东西就是一个二分图

因为他能够被分成 u u u, v v v两部分, u u u中的点相互之间没有连边, v v v中的点相互之间也没有连边
二分图也叫做二部图,偶图等等
在OI中,几乎所有二分图的题目都可以用网络流来实现,但是二分图本身是有非常优秀的算法的,下面我们来介绍一下

2.二分图的判定

2.1 定义法判定二分图

二分图的判定方法就是基于他的定义的
显然,根据定义,一个二分图不能存在奇环
如果存在奇环的话显然不是一个二分图,这个大家可以参照上面的图理解一下,应该不难
那么这道题的内容就转化成了判断一个图是否有奇环
这个做法怎么做呢?
我们常见的做法是进行黑白染色
给有边连接的两个点染成不同的颜色,如果dfs(bfs)的过程中,出现一个点的标记颜色和我们要标的颜色不同的话,那么就出现了奇环,这个图就不是二分图
当然判断二分图还有其他方法比如拓扑排序之类的,但是这种做法有一个优点就是他最后直接为我们分好了两部分
简单的放一下这种做法的代码

inline void dfs(int u,int c){
   
   
	color[u]=c;
	for(int i=head[u];~i;i=e[i].next){
   
   
		int v=e[i].to;
		if(color[v]==-1)dfs(v,c^1);
		else if(color[v]==c){
   
   
			puts("0");
			exit(0);
		}
	}
}

2.2 二分图判定方法的应用

NOIP2008 双栈排序
这道题的做法就是根据进哪个栈预处理出一个图,如果不是二分图就无解,如果是二分图就有解,然后根据题目要求输出就可以了

3.二分图匹配

3.1 增广路

先说题目意思吧,二分图匹配是我们要让二分图一部分的点尽可能的去匹配另一部分的点,当然一个点只能匹配一个点啦

这里我们要引入一个叫做增广路的东西,这也是网络流的基础
比如说对于这样的一个二分图
在这里插入图片描述
我们现在要进行匹配,那么我们先枚举左边的点,从第一个开始
匹配右边的第一个
在这里插入图片描述
当我们枚举第二个点的时候,我们发现,他已经不能和第一个匹配了,所以我们连向右边第三个点
在这里插入图片描述
然后我们枚举左边的第三个点,他已经不能和右边第三个匹配了,但是他没有别的出边了,怎么办呢,我们观察这条红色的路径
在这里插入图片描述
这条路径,从左3出发,经过未匹配边->匹配边->未匹配边->匹配边->未匹配边,我们发现,如果我们把这条路径上的匹配情况整体取反一下,匹配边变成未匹配边,未匹配边变成匹配边,就变成了
在这里插入图片描述
那么我们发现,这时候匹配数就增加了1!
像这样,经过未匹配边->匹配边->…->匹配边->未匹配边的一条路径,就叫做一条增广路

3.2 匈牙利算法

匈牙利算法正是基于增广路的一种解决二分图匹配的做法
我们发现,当我们找到一条增广路,我们把这条路径上的所有匹配关系取反之后,匹配数就+1,那么匈牙利算法就是不停的找增广路,一旦找到一条,那么就整体匹配关系取反,答案+1
那么实现也很简单,大概放下代码吧

bool dfs(int u){
   
   
    if(vis[u])return false;//vis表示这一次找增广路的时候有没有访问过这个点,如果一个点之前已经访问过了说明找不到增广路
    vis[u]=true;
    RepG(i,u){
   
   //枚举出边
        int v=e[i].to;
        if(!match[v]||dfs(match[v])){
   
   
        //match[v]表示v点之前匹配的点,如果v之前还没有一个点和他匹配,或者往他之前匹配的那个点去找增广路找到了
        //就把匹配关系在回溯的时候整体取反一下,让match[v]=u,然后返回true说明找到了一条增广路
            match[v]=u;
            return true;
        }
    }
    return false;//如果没找到,返回false
}

void hungary(){
   
   
    Rep(i,1,totx){
   
   
        memset(vis,0,sizeof(vis));
        if(dfs(i))ans++;//如果找到了增广路,就说明这个点能匹配上,答案+1
    }
}

匈牙利算法的复杂度可以证明是 O ( n m ) O(nm) O(nm)的,因为每个点都要枚举一遍,最差情况下每条边都要经过一遍,但是这只是最差情况下复杂度,大家如果接触过网络流的话就知道网络流的复杂度是很难跑满的

3.3 网络流求二分图匹配

网络流我之前有讲过,大家可以看这里
用网络流跑二分图匹配就是建立一个超级源点和汇点,源点往左半部分每个点连一个容量为1的边,右半部分每个点往汇点连一个容量为1的点,然后每条边都相应的连上,容量均为1,就可以跑最大流了,最后的答案就是最大流量
那么问题来了,怎么判断最后匹配的情况呢?
因为用匈牙利的话我们可以直接用match看出匹配情况,但是网络流怎么看呢?
我们可以判断原图上的每一条边,他的反边是否有流量(因为这道题容量都是1,看正边容量是不是0也行),如果有,说明这两个点是匹配的
用 d i n i c dinic dinic求二分图匹配的复杂度最差可以证明是 O ( n n ) O(n\sqrt n) O(nn ​),一样也是通常跑不到
而且一般出题人也不会看匈牙利吧
代码就不放了

3.4 二分图匹配的应用

应用就很多了,这也是二分图匹配最常考的了
最常见的就是两种题型吧,一个是题目里明确说了要匹配的,正常连边就可以
还有一个是二分图的一个转化模型,比如说放棋子,每行只能放一个,每列只能放一个这种的,那么我们可以把每一行当成左半部分的点,每一列当成右半部分的点,每个能放棋子的地方就把他的行向列连一条边就可以了,这样的题目也不少,比如说
P1263 宫廷守卫 上面的模型稍微变化一下就好了
[SCOI2015] 小凸玩矩阵 二分一下就好等等
然后还有一些其他的,比如说
[JSOI2016] 反质数序列判断质数,按奇偶性连边
这里就不一一列举了

4.二分图最小点覆盖

4.1 定义

二分图最小点覆盖的定义对于一个二分图,选择最少的点,让图中所有的边至少有一个端点属于这些点

4.2 二分图最小点覆盖定理

内容
二分图最小点覆盖定理:二分图最小点覆盖=二分图最大匹配数
证明
我们先构造出一个二分图的匹配情况
在这里插入图片描述
我们从左侧每一个没有被匹配的点出发(在这幅图是左2,5),走所有不完全的增广路,就是说构成是 未匹配边->匹配边->…->匹配边这样的路径,标记经过的点,这幅图中应该有两条,分别是
在这里插入图片描述
红色的和蓝色的这两条
然后我们看左半部分没有被访问过的(左3)和右半部分被访问过的(右2,4)
这就是我们二分图的一个最大独立集
为什么呢?

我们可以用反证法来证明
假设还有一条边没有被这几个点覆盖,那么显然他的左端点是一个匹配了的点
当这条边是一个匹配边时
如果这条边的右端点只有一条边,那么他的右端点不会访问到,所以没有一条不完全增广路会从右边过来,而左端点又不是不完全增广路的起点(因为已经匹配),所以他不会被覆盖,所以他的左端点属于左边没有被访问到的点,矛盾
如果这条边的右端点有大于一条边,那么他一定会属于一条不完全增广路,那么右端点一定属于右边别访问到的点,矛盾
当这条边不是一个匹配边时
他连向的点一定是右边被访问的,所以这条边也别覆盖,矛盾。
所以这些点一定可以覆盖所有的边

下面要证明这些点少一个一定不行,这个证明方法跟上面类似,这里就不再过多赘述了,大家可以下去自己证一下。

那么通过这种构造方法,就得到了一个二分图最小点覆盖。
那么为啥这个最小点覆盖是最大匹配数呢?
我们可以逆着增广路来想,每个右边被访问过的点一定对应一条匹配边,左边每个没有被访问过的点一定也对应一条匹配边(如果左边点没有被匹配他就是不完全增广路的起点了),所以我们得到结论

二 分 图 最 小 点 覆 盖 = 二 分 图 最 大 匹 配 数 \boxed{二分图最小点覆盖=二分图最大匹配数}

二分图 文章目录二分图**一. 二分图的判断二.二分图的最大匹配三. 二分图最小点覆盖和最大独立集四. 二分图的最大权匹配 二分图** 二分图又称作二部图, 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。通俗来讲,就是二分图中的每一条边的两个顶点,... 阅读详情

相关推荐

二分图的一些概念

什么是二分图若图G的结点集V(G)可以分成两个非空子集 V1和V2,并且图G的任意边xy关联的两个结点 x、y分别属于这两个子集,则图G是二分图。所有的树都是二分图。从树中任取一个结点为树根,着上白色,然后将根的所有孩子着上黑色,将下一层再着白色,继续此过程直到所有结点都着色。用着色法或标记法可以检测一个给定的图是不是十分图。偶数个结点的圈是二分图,而奇数个结点的圈不是二分图。所以如果图中含有奇圈

tanzhangwen的专栏 3307

STK轨道仿真环境搭建实战:从地月系到多天体场景

本文详细介绍了STK轨道仿真环境搭建的实战指南,从基础的地月系统到复杂的多天体场景。通过逐步操作说明和实用技巧,帮助用户快速掌握STK软件的使用方法,提升轨道仿真效率,适用于航天任务设计和教学演示。

weixin_30312563的博客 396

MID360+fastlio功能笔记

前言。

qq_35598561的博客 5295

win11下的MySQL安装

目前官方最新版本是8.0.26,考虑到其稳定性、可靠性还需一定周期保证,所以使用官方版求稳定仍然建议5.7系列。3、选择MySQL Servers 5.7.38 -x64,然后按绿色箭头将选中的版本移植到右边选中框中。4、点击下方蓝色Advanced Options,选择安装位置。1、在开始界面搜索MySQL,点击command line。4、在“系统变量”中选择“path”,点击编辑。5、新建——>增加MySQL路径——>确定,12、execute,安装好后next。9、不需要做修改,直接点击next。.

rensweet的博客 2万+

ur3手眼标定+realsenseL515

知乎 csdn

AI_future的博客 976

实干派!网易易盾增强版滑块验证码,全方位讲解识别思路(含源码)

该验证码是异形滑块验证码中的一种,缺口旋转+偏移的处理需要你有很好的图像处理知识,能很好的处理透明通道,同时,该验证码需要你能很好的处理缺口和背景之间匹配的关系,该验证码的处理难点就是两个缺口之间如何找到正确的,两个检测框都有很强的相似度,且加上背景图的干扰,在图像处理和有优化上难度大大增加。

码王吴彦祖的博客 2014

第069篇:浸入边界法进阶

浸入边界法(Immersed Boundary Method, IBM)是处理流固耦合问题的强大数值方法。本文深入介绍直接力法、反馈力法、Ghost Cell方法和多域IBM等高级技术。通过Python实现完整的IBM求解器,展示处理移动边界、弹性边界和多体相互作用的方法。浸入边界法,直接力法,反馈力法,Ghost Cell,流固耦合,移动边界,弹性边界Navier-Stokes方程添加体积力项:∂u∂t+(u⋅∇)u=−1ρ∇p+ν∇2u+f\frac{\partial \mathbf{u}}{\part

2401_87715305的博客 412

【某音电商】protobuf聊天协议逆向

某音电商私信、聊天消息protobuf协议逆向分析与解析

吴秋霖的博客 2314

HANA-公司间销售ICS-IDOC系统配置-保姆级配置文档

合作伙伴编号:这个客户表示收票方(销售公司在生产公司中所对应的客户代码,卖方开票,买方收票),也就是咱们在配置消息类型输出的时候合作伙伴的类型的一个具体的客户编码,这个是站在发货工厂的角度去看的,也就是EDI 输出的 BP 合作伙伴的编号;在项目实施过程中经常会遇到关联方交易的问题,有公司间采购的业务场景,也会存在公司间销售的业务场景,本文将着重讲解公司间销售在SAP系统中的实现场景。在这个过程中,销售公司向客户开票产生应收,而生产公司向销售公司开票产生自己的应收,同时销售公司向生产公司产生应付。

我小时候很黑的博客 2389

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

怀旧版电脑GBC模拟器

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

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

上一篇: Codeforces Round 627(div.3)
下一篇: [POI2011] DYN-Dynamite
NephrenRuqInsania
博客等级 码龄8年 20粉丝 115原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值