题解 P3386 【【模板】二分图匹配】
首先呢声明一下,本宝宝发这篇题解只是为了(goto a;)
个人还是比较喜欢跑dinic暴力跑最大流。。。竟然比匈牙利还快。。
如果说不懂网络流的~~蒟蒻~~大佬们。
可以看看这个(反正我就是在这篇文章看懂的)
好啦,言归正传。
a:本宝宝想解释一下为什么这道题可以用网络流水过233....
首先我们看看二分图的概念。标准概念是:
简单的说,一个图被分成了两部分,相同的部分没有边,那这个图就是二分图,二分图是特殊的图。(摘自这里)
如果你看不懂的话,那么请看某大佬给宝宝讲的时候的解释:
~~一群汉子和一群妹子匹配。没有基友也没百合,不能开后宫,这就是二分图。最大匹配就是求能组成的CP最多多少对~~ 可能题解不过就是因为这句话233(逃~)
网络流最重要的是要建图!建图!建图!那么看看这道题怎么建图。
我们发现对于左边的n个点和右边的m个点。如果说最好的情况下。匹配的~~个~~对数是$min(m,n)$也就是说,我们左边尽可能的通过已有的边流到右半部分统计一下流到右半部分的容量最大值就是答案了(当然是要边的容量都是1的时候最简单了)。
所以我们将源点S设在左半部分左边,向左边所有的点连一条容量为1的边。汇点T设在右半部分的右边。从所有的右半部分的点连向汇点一条容量为1的边,暴力跑一边dicnic就好啦。
所以建边代码:
- scanf("%d%d%d",&n1,&m1,&e1);
- n=n1+m1+;//源点编号为1,汇点编号为总点数+1
- for(int i=;i<=n1;i++)
- {
- add(,i+,);//空过源点,所以i+1,这里在连接源点和左部点。
- add(i+,,);
- }
- for(int i=;i<=e1;i++)
- {
- int u,v;//连已有的边
- scanf("%d%d",&u,&v);
- if(u<=n1&&v<=m1)
- add(u+,v+n1+,),
- add(v+n1+,u+,);
- }
- for(int i=;i<=m1;i++)
- {
- add(i+n1+,n,);//连右部点和汇点
- add(n,i+n1+,);
- }
好啦完整代码奉上:
- #include<iostream>
- #include<algorithm>
- #include<cstdio>
- #include<cstring>
- using namespace std;
- int n,m;
- int cnt=;
- int alist[];
- struct data{
- int v;int next;int value;
- }edge[];
- void add(int u,int v,int value)
- {
- edge[cnt].v=v;
- edge[cnt].value=value;
- edge[cnt].next=alist[u];
- alist[u]=cnt++;
- return ;
- }
- int h[];
- int q[];
- //dicnic暴力参见上面提到的博客。
- bool bfs()
- {
- int x,next;
- memset(h,-,sizeof(h));
- int head=,tail=;
- q[head]=;
- h[]=;
- while(head<tail)
- {
- x=q[head++];
- next=alist[x];
- while(next)
- {
- int v=edge[next].v;
- int value=edge[next].value;
- if(value&&h[v]<)
- {
- q[tail++]=v;
- h[v]=h[x]+;
- }
- next=edge[next].next;
- }
- }
- // for(int i=1;i<=n*m;i++) printf("h[%d]=%d\n",i,h[i]);
- if(h[n]==-) return false;
- return true;
- }
- int ans;
- int dfs(int x,int y)
- {
- if(x==n) return y;
- int next=alist[x];
- int w,used=;
- while(next)
- {
- int v=edge[next].v;
- int value=edge[next].value;
- if(value&&h[v]==h[x]+)
- {
- w=y-used;
- w=dfs(v,min(w,value));
- edge[next].value-=w;
- edge[next^].value+=w;
- used+=w;
- if(used==y) return y;
- }
- next=edge[next].next;
- }
- if(!used) h[x]=-;
- return used;
- }
- void dinic()
- {
- while(bfs()) ans+=dfs(,0x7fffffff);
- }
- int n1,m1,e1;
- int main()
- {
- // freopen("testdata.in","r",stdin);
- //第一遍没A就是因为忘了删上面这句话。。。
- scanf("%d%d%d",&n1,&m1,&e1);
- n=n1+m1+;
- for(int i=;i<=n1;i++)
- {
- add(,i+,);
- add(i+,,);
- }
- for(int i=;i<=e1;i++)
- {
- int u,v;
- scanf("%d%d",&u,&v);
- if(u<=n1&&v<=m1)
- add(u+,v+n1+,),
- add(v+n1+,u+,);
- }
- for(int i=;i<=m1;i++)
- {
- add(i+n1+,n,);
- add(n,i+n1+,);
- }
- dinic();//暴力跑最大流
- printf("%d",ans);
- return ;//程序拜拜
- }
好啦这道题就先这样。对于要刷网络流的大佬们要是想练一练怎么见图的话P1402是一个很好的选择。
然后想深入学习的同学可以看看最小割和转对偶图。之后做一下P4001
题解 P3386 【【模板】二分图匹配】的更多相关文章
- [洛谷P3386] [模板] 二分图匹配 (匈牙利算法)
题目传送门 毒瘤出题人zzk出了个二分图匹配的题(18.10.04模拟赛T2),逼我来学二分图匹配. 网络流什么的llx讲完之后有点懵,还是匈牙利比较好理解(绿与被绿). 对于左边的点一个一个匹配,记 ...
- 【洛谷 p3386】模板-二分图匹配(图论)
题目:给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数. 解法:匈牙利算法.(以前我总是不记得......)实质上应该有贪心的思想,每次都尽量匹配,找到能和自己匹配的也尽量让它们匹配 ...
- 模板——二分图匹配KM
具体方法就不介绍了,详见 https://blog.csdn.net/sixdaycoder/article/details/47720471 主要讲一些注意点: 1:不直接将未匹配的y减小是因为要保 ...
- 【BZOJ1562】【NOI2009】变换序列(二分图匹配)
[BZOJ1562][NOI2009]变换序列 题面 BZOJ 洛谷 这题面写的是真的丑,还是先手动翻译成人话. 让你构造一个\(0..N-1\)的排列\(T\) 使得\(Dis(i,T_i)\)为给 ...
- P3386 【模板】二分图匹配(匈牙利&最大流)
P3386 [模板]二分图匹配 题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正 ...
- 洛谷—— P3386 【模板】二分图匹配
P3386 [模板]二分图匹配(复习) 题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每 ...
- luogu P3386 【模板】二分图匹配
二次联通门 : luogu P3386 [模板]二分图匹配 /* luogu P3386 [模板]二分图匹配 最大流 设置源点,汇点,连到每条边上 跑一边最大流即可 */ #include <i ...
- P3386 【模板】二分图匹配
题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正整数u,v,表示u,v有一条连边 ...
- AC日记——【模板】二分图匹配 洛谷 P3386
题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正整数u,v,表示u,v有一条连边 ...
- 洛谷 P3386 【模板】二分图匹配
题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正整数u,v,表示u,v有一条连边 ...
随机推荐
- python‘s tenth day for me
动态参数 *args **kwargs *args 动态参数,万能参数 # args 接受的就是实参对应的 所有位置参数,并将其放在元祖中. def func(*args): pri ...
- SqlConnection 无法设置连接超时
1.最有效的方法:对表格建立索引 2 在连接字符串中设置 Connection Timeout (默认15秒)3 设置 SqlCommand.CommandTimeout(默认是 30 秒)
- Internet Explorer 无法打开该 Internet 站点,请求的站点不可用或无法找到
笔者最近遇见一个神奇的问题,同事在开发时用的谷歌浏览器,实现了一个下载功能,测试也没问题:但测试人员反馈说他那边没法下载,报异常.弹出框 同事跑过来和我商讨这个问题,笔者当时就懵了,于是赶紧查找相关资 ...
- wordpress get_query_var()函数
get_query_var函数的最主要作用就是能够查询得到当前文章的分类及分页.定义在:wp-includes/query.php 定义: function get_query_var($var) { ...
- JVM中的JIT
JVM中的JIT 介绍Java虚拟机的文章或者书籍总会提到Java虚拟机中的JIT编译器,可是JIT编译器到底是什么?为什么需要JIT编译呢? JIT编译器,是Just In Time编译的意思,又称 ...
- Java多线程-新特征-阻塞栈LinkedBlockingDeque
对于阻塞栈,与阻塞队列相似.不同点在于栈是“后入先出”的结构,每次操作的是栈顶,而队列是“先进先出”的结构,每次操作的是队列头. 这里要特别说明一点的是,阻塞栈是Java6的新特征.. Java为阻塞 ...
- ArcGIS JS API实现的距离测量与面积量算
转自https://www.cnblogs.com/deliciousExtra/p/5490937.html
- 获取文件的后缀名。phpinfo
1: function get_extension($file){ //strrchr 返回 .jpg substr :1 是从1开始. substr(strrchr($file,'.'),1) } ...
- mybatis学习笔记 spring与mybatis整合
转载自http://blog.csdn.net/naruto_Mr/article/details/48239357 1.创建web工程,导入spring依赖包与mybatis依赖包,还需要mybat ...
- Solidity oraclize query apikey加密
solidity 程序中如果用到oraclize query,api调用需要apikey,则最好加密apikey,否则公开solidity代码时会连同apikey一起公开. 加密方法: https:/ ...