题解 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有一条连边 ...
随机推荐
- 【树莓派智能门锁】使用脚本控制GPIO来开锁【4】
假定你已经通过此文章或者其他方式完成了树莓派的基本配置 [树莓派]RASPBIAN镜像初始化配置 我们通过VNC View连接到树莓派查看一下~ 1.更新一下基本的设置:更新一下源,把python-d ...
- 【知识碎片】python 篇
领域:运维 网站 游戏 搜索 嵌入式 C/S软件 Openstack二次开发 绿色版:Portable Python 面向对象.解释型动态语言 env python 切换版也好使,自己寻找系统中pyt ...
- Idea搭建Scala开发环境的注意事项
Idea搭建Scala开发环境的注意事项 1.下载ideaIC-2017.3.tar.gz 2.解压安装idea 3.File->setting->plugins 下载2个插件scala. ...
- 【bzoj2186】[Sdoi2008]沙拉公主的困惑
2186: [Sdoi2008]沙拉公主的困惑 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 3303 Solved: 1129[Submit][S ...
- win7 下安装mysql 整理
1.去官网下载mysql-5.6.13-winx64.zip包.地址: http://dev.mysql.com/downloads/mysql/5.6.html 2,把安装包解压到自己指定的目录,我 ...
- 在CenOS7.5里安装Redis
一.系统环境 操作系统:CentOS 7.5 Redis版本:redis3.2.8 登录账号:Frank 二.安装过程 A.预安装,安装gcc 1.进入终端,切换到root账号 2.输入指令: yum ...
- 在Ubuntu上源码安装NodeJS
Refer http://nqdeng.github.io/7-days-nodejs/#7.1 前提条件: 确保系统下g++版本(g++ -v)在4.6以上,python版本(python --ve ...
- 《the art of software testing》第五章
构建大型程序测试的第一个步骤:模块测试 测试用例的设计 在为模块测试设计测试用例时,需要两种信息:模块的规格说明和模块源代码: 模块测试总体上面向白盒测试: 模块测试的测试用例设计过程:使用一种或多种 ...
- 好的linux网站
site:www.tldp.org rpm http://www.computerhope.com/unix.htm
- linq to sql 实现左(右)连接,那个方法是对的,该怎么处理
linq to sql 实现左(右)连接,那个方法是对的var query2 = from tb0 in db.table_0 join tb1 in db.table_1 on table_0.关 ...