AC日记——【模板】二分图匹配 洛谷 P3386
题目背景
二分图
题目描述
给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数
输入输出格式
输入格式:
第一行,n,m,e
第二至e+1行,每行两个正整数u,v,表示u,v有一条连边
输出格式:
共一行,二分图最大匹配
输入输出样例
输入样例#1:
1 1 1 1 1
输出样例#1:
1
说明
n,m<=1000,1<=u<=n,1<=v<=m
因为数据有坑,可能会遇到v>m的情况。请把v>m的数据自觉过滤掉。
算法:二分图匹配
思路:
二分图模板;
来,上代码:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define maxn 1005 #define INF 0x7fffffff using namespace std; struct EdgeType { int v,f,e; }; struct EdgeType edge[maxn*maxn*2]; int cnt,deep[maxn<<1],ans,e; int n,m,head[maxn<<1],s=0,t=(maxn<<1)-1; char Cget; inline void in(int &now) { now=0,Cget=getchar(); while(Cget>'9'||Cget<'0') Cget=getchar(); while(Cget>='0'&&Cget<='9') { now=now*10+Cget-'0'; Cget=getchar(); } } bool bfs() { for(int i=s;i<=t;i++) deep[i]=-1; queue<int>que;deep[s]=0,que.push(s); while(!que.empty()) { int now=que.front();que.pop(); for(int i=head[now];i;i=edge[i].e) { if(edge[i].f>0&&deep[edge[i].v]<0) { deep[edge[i].v]=deep[now]+1; if(edge[i].v==t) return true; que.push(edge[i].v); } } } return false; } int flowing(int now,int flow) { if(now==t||flow<=0) return flow; int oldflow=0; for(int i=head[now];i;i=edge[i].e) { if(edge[i].f<=0||deep[edge[i].v]!=deep[now]+1) continue; int pos=flowing(edge[i].v,min(edge[i].f,flow)); if(pos>0) { flow-=pos; oldflow+=pos; edge[i].f-=pos; edge[i^1].f+=pos; if(flow==0) return oldflow; } } if(oldflow==0) deep[now]=-1; return oldflow; } int main() { in(n),in(m),in(e); for(int i=1;i<=n;i++) { edge[++cnt].v=i,edge[cnt].f=1,edge[cnt].e=head[s],head[s]=cnt; edge[++cnt].v=s,edge[cnt].f=0,edge[cnt].e=head[i],head[i]=cnt; } for(int i=1+n;i<=m+n;i++) { edge[++cnt].v=t,edge[cnt].f=1,edge[cnt].e=head[i],head[i]=cnt; edge[++cnt].v=i,edge[cnt].f=0,edge[cnt].e=head[t],head[t]=cnt; } int u,v; while(e--) { in(u),in(v);v+=n; edge[++cnt].v=v,edge[cnt].f=1,edge[cnt].e=head[u],head[u]=cnt; edge[++cnt].v=u,edge[cnt].f=0,edge[cnt].e=head[v],head[v]=cnt; } while(bfs()) ans+=flowing(s,INF); cout<<ans; return 0; }