题目背景
二分图
题目描述
给定一个二分图,结点个数分别为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的数据自觉过滤掉。
算法:二分图匹配
网络流 最大流
Dinic水过
RE了无数次
一定开大数组!!
#include <cstdio> #include <queue> using namespace std; #define Max 1000000 #define inf 1e9 struct edge { int to,next,dis; }edge[Max*5]; int ans,head[Max*5],cnt=1,dep[Max*2],n,m,e; void add(int u,int v,int l) { edge[++cnt].next=head[u]; edge[cnt].to=v; edge[cnt].dis=l; head[u]=cnt; } bool bfs(int s,int t) { queue<int>q; for(int i=s;i<=t;++i) dep[i]=inf; dep[s]=0; q.push(s); while(!q.empty()) { int tp=q.front(); q.pop(); for(int i=head[tp];i;i=edge[i].next) { if(dep[edge[i].to]>dep[tp]&&edge[i].dis>0) { dep[edge[i].to]=dep[tp]+1; if(edge[i].to==t) return 1; q.push(edge[i].to); } } } return 0; } int dfs(int now,int t,int came_flow) { if(now==t||came_flow<=0) return came_flow; int res=0,f; for(int i=head[now];i;i=edge[i].next) { if(dep[edge[i].to]==dep[now]+1&&edge[i].dis>0&&(f=dfs(edge[i].to,t,min(edge[i].dis,came_flow)))) { edge[i].dis-=f; edge[i^1].dis+=f; res+=f; came_flow-=f; if(came_flow<=0) break; } } return res; } int dinic(int s,int t) { while(bfs(s,t)) ans+=dfs(s,t,inf); return ans; } int main() { scanf("%d%d%d",&n,&m,&e); for(int u,v;e--;) { scanf("%d%d",&u,&v); if(u<=n&&v<=m) { add(u,v+n,1); add(v+n,u,0); } } for(int i=1;i<=n;++i) add(0,i,1),add(i,0,0); for(int i=n+1;i<=m+n;++i) add(i,m+n+1,1),add(m+n+1,i,0); printf("%d",dinic(0,m+n+1)); return 0; }