题解 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 twenty-second day for me 封装,property方法
面对对象的三大特性:继承,多态,封装. 函数和属性装到了一个非全局的命名空间----封装. 封装: 在类中,静态属性,方法,对象属性都可以变成私有的,只需要在这些名字前加上‘__’(双下划线). 在类 ...
- Python Twisted系列教程9:第二个小插曲,Deferred
作者:dave@http://krondo.com/a-second-interlude-deferred/ 译者:杨晓伟(采用意译) 可以从这里从头来阅读这个系列 更多关于回调的知识 稍微停下来再思 ...
- Halcon学习之文本操作
1. 新建文本文件open_file ( : : FileName, FileType : FileHandle ) 创建 ( 'output' or 'append' )或者打开 ...
- MyEclipse从数据库反向生成实体类通过Hibernate的方式----mysql数据库实例
1.我们通过DB与数据库建立连接 2.建立web工程,构建Hibernate框架 3.通过table生成实体类
- flask+jsonp跨域前后台交互(接口初体验)
1 # -*- coding: utf-8 -*- 2 from flask import Flask, jsonify 3 import psutil, time,json 4 5 app = Fl ...
- 2-javascript::笔记
0.位置: HTML 中的脚本必须位于 <script> 与 </script> 标签之间. 脚本可被放置在 HTML 页面的 <body> 和 <head& ...
- NOIP2018 解题笔记
D1T1 铺设道路 在场上并没有想到积木大赛这道原题. 差分之后可以把在$[l, r]$这段区间$ - 1$变成在$l$处$ - 1$,在$r + 1$处$ + 1$,然后最终目标是使$\forall ...
- MVC 知识点随笔
1.https://msdn.microsoft.com/zh-cn/gg981918 <text></text> 等同于 @:
- Ubuntu下成功安装台式机网卡realtek的rtl8188eu芯片驱动并实现AP功能
1,下载驱动 https://github.com/lwfinger/rtl8188eu 使用注意: https://github.com/lwfinger/rtl8188eu/issues/3 2. ...
- 事物处理service层的方法
package cn.lijun.service; import java.sql.Connection;import java.sql.SQLException; import cn.lijun.d ...