题解 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有一条连边 ...
随机推荐
- Git第三方仓库安装方式(IUS)
1.安装使用里面说的自动化安装脚本 curl https://setup.ius.io | sh 2.然后可以看到 git2u相关内容 yum search git 3.执行安装,并查看下版本 yum ...
- ffmpeg函数介绍
本文对在使用ffmpeg进行音视频编解码时使用到的一些函数做一个简单介绍,我当前使用的ffmpeg版本为:0.8.5,因为本人发现在不同的版本中,有些函数名称会有点小改动,所以在此有必要说明下ffmp ...
- cuteFTP软件往linux中上传文件时报…
我是在win7和VM中的ubuntu传输文件: 使用一个客户端,可以正常的连接,但是当上传文件时,总是报553 Could not create file错误信息. 主要原因是新建的文件夹没有更改权限 ...
- schedule和scheduleAtFixedRate的区别
- js中 visibility和display的区别 js中 visibility和display的区别
大多数人很容易将CSS属性display和visibility混淆,它们看似没有什么不同,其实它们的差别却是很大的. visibility属性用来确定元素是显示还是隐藏,这用visibility=&q ...
- 今天写shader流光效果,shader代码少了个括号,unity shader compiler卡死且不提示原因
今天写shader流光效果,shader代码少了个括号,unity shader compiler卡死且不提示原因 好在找到了原因,shader 代码如下,原理是提高经过的颜色亮度 void surf ...
- C++——多线程
1.多进程和多线程:进程是一个总任务,一个进程可能包含多个线程. 2.并行和并发: 并发的关键是你有处理多个任务的能力,不一定要同时. 并行的关键是你有同时处理多个任务的能力. 3.共享数据的管理和线 ...
- jQuery基础教程-第8章-003Providing flexible method parameters
一.The options object 1.增加阴影效果 (function($) { $.fn.shadow = function() { return this.each(function() ...
- Linux xclip命令
一.简介 xclip命令建立了终端和剪切板之间通道,可以用于以命令的方式将终端输出或文件的内容保存到剪切板中,也可以用于将剪切板的内容输出到终端或文件中. 在 X 系统里面,从一个窗口复制一段文字到另 ...
- Linux Valgrind命令
一.简介 C/C++程序,最常见的错误之一就是内存泄露.Valgrind 是一款 Linux下的内存调试工具,它可以对编译后的二进制程序进行内存使用监测找出内存泄漏问题. Valgrind通常包括如下 ...