P3386 【模板】二分图匹配 -网络流版
二分图匹配
题目背景
二分图
感谢@一扶苏一 提供的hack数据
题目描述
给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数
输入输出格式
输入格式:
第一行,n,m,e
第二至e+1行,每行两个正整数u,v,表示u,v有一条连边
输出格式:
共一行,二分图最大匹配
输入输出样例
说明
n,m \leq 1000n,m≤1000 , 1 \leq u \leq n1≤u≤n , 1 \leq v \leq m1≤v≤m
因为数据有坑,可能会遇到 v>mv>m 的情况。请把 v>mv>m 的数据自觉过滤掉。
算法:二分图匹配
思路
dinic跑二分图最大流
一个源点(0)连接1到n
一个汇点(n+m+1)连接n+1到n+m
套上板子就可以了
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #define inf 0x3f3f3f3f 6 #define maxn 2010001 7 using namespace std; 8 9 int n,m,s,t; 10 struct node{ 11 int v,next,cap; 12 }e[maxn]; 13 int head[maxn],tot=1; 14 int dis[maxn]; 15 16 void add_node(int a,int b,int c) 17 { 18 e[++tot]=(node){b,head[a],c}; 19 head[a]=tot; 20 } 21 22 bool bfs() 23 { 24 memset(dis,-1,sizeof(dis)); 25 queue<int> q; 26 q.push(s); 27 dis[s]=0; 28 while(!q.empty()) { 29 int x=q.front(); 30 q.pop(); 31 for(int i=head[x];i;i=e[i].next) 32 { 33 int v=e[i].v; 34 if(e[i].cap&&dis[v]==-1) 35 { 36 dis[v]=dis[x]+1; 37 q.push(v); 38 } 39 } 40 } 41 return dis[t]!=-1; 42 } 43 44 int dfs(int now,int f) 45 { 46 if(now==t) return f; 47 int rest=f; 48 for(int i=head[now];i;i=e[i].next) 49 { 50 int v=e[i].v; 51 if(e[i].cap&&rest&&dis[v]==dis[now]+1) 52 { 53 int t=dfs(v,min(rest,e[i].cap)); 54 if(!t) dis[v]=0; 55 e[i].cap-=t; 56 e[i^1].cap+=t; 57 rest-=t; 58 } 59 } 60 return f-rest; 61 } 62 63 void dinic() 64 { 65 int ans=0; 66 while(bfs()) 67 ans+=dfs(s,inf); 68 printf("%d",ans); 69 } 70 71 int main() 72 { 73 int ee; 74 scanf("%d%d%d",&n,&m,&ee); 75 int x,y; 76 for(int i=1;i<=ee;++i) { 77 scanf("%d%d",&x,&y); 78 if(x>n||y>m) continue; 79 add_node(x,y+n,1); 80 add_node(y+n,x,0); 81 } 82 s=0;t=n+1+m; 83 for(int i=1;i<=n;++i) { 84 add_node(s,i,1); 85 add_node(i,s,0); 86 } 87 for(int i=1;i<=m;++i) { 88 add_node(n+i,t,1); 89 add_node(t,n+i,0); 90 } 91 dinic(); 92 return 0; 93 }