二分图匹配学习记
这个博客目前还没更完
刚开始打的时候被毒瘤死了。。
Leve1 洛谷 P3386 【模板】二分图匹配
匈牙利算法[Hungury算法]
题目大意:给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数
一级代码
1 进入dfs后,判断是否存在已经访问的情况 2 然后枚举每一条与之相邻的边 3 然后得到另一个点,这样做下去,判断是否存在一个未被访问或者一个可以改变自己的匹配的点 4 接着dfs回溯,显然这个点也能够匹配了 5 然后return即可
这里说一下第三步的意思
例如这张图,这个过程就像找媳妇
开始找到一个没有被访问的点
好的,现在我们左边第一个点找到媳妇了
然后第一个点完成,扫描第左边二个点,当第左边二个点愤怒地发现左边第一个点抢了他唯一能抢到的媳妇,这不得行啊,交涉交涉。
于是按照蓝点的路径左边第一个点发动干涉后,第一个点说,好吧,反正我媳妇挺多的
守国外武装干涉势力影响……
幸福且美满的结局……
那么现在代码就显而易见的简洁
#include<iostream> #include<cmath> #include<cstdio> #include<cstring> #include<queue> #include<stack> #include<vector> using namespace std; int head[10086],size,n,m,ee,have_meizi[10086],tot,vis[100860]; struct edge{ int next,to; }e[1008600]; void addedge(int next,int to) { e[++size].next=head[next]; e[size].to=to; head[next]=size; } int ycl(int a) { return a+n; } int hungary(int s) { int i,j; for(i=head[s];i;i=e[i].next) { j=e[i].to; if(vis[j]) continue; vis[j]=1; if(!have_meizi[have_meizi[j]]) { have_meizi[j]=s; return 1; } else { if(hungary(have_meizi[j])) { have_meizi[j]=s; return 1; } } } return 0; } int main() { int i,j; scanf("%d %d %d",&n,&m,&ee); for(i=1;i<=ee;i++) { int t1,t2; scanf("%d %d",&t1,&t2); if(t1>n||t2>m||t1>m||t2>n) continue; //t2=ycl(t2); addedge(t1,t2); } for(i=1;i<=m;i++) { memset(vis,0,sizeof(vis)); if(hungary(i)) tot++; } printf("%d",tot); return 0; }
显然,这道题裸的的hack数据是精心构造的,然后这也会是新手的一个误区(比如我),
hack数据:
input 5 5 11 1 2 1 5 2 2 2 3 2 4 3 1 3 5 4 1 4 2 4 5 5 2 output 4