题目描述
给定一个二分图,结点个数分别为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 的数据自觉过滤掉。
算法:二分图匹配
题解
- 看这题目也看着像板题,就是模板题,匈牙利、最大流两种做法
代码1
1 #include <cstdio>
2 #include <iostream>
3 #include <queue>
4 #define inf 0x3f3f3f3f
5 using namespace std;
6 queue<int>Q;
7 struct edge {int to,from,v;}e[2001000];
8 int n,m,num,cnt,ans,s,t,dis[1010*4],head[1010*4],cur[1010*4];
9 void insert(int x,int y,int z) { e[++cnt].to=y,e[cnt].from=head[x],e[cnt].v=z,head[x]=cnt; }
10 bool bfs()
11 {
12 for (int i=s;i<=t;i++) dis[i]=0; dis[s]=1;
13 while (!Q.empty()) Q.pop(); Q.push(s);
14 while (!Q.empty())
15 {
16 int u=Q.front(); Q.pop();
17 for (int i=head[u];i;i=e[i].from)
18 if (e[i].v&&!dis[e[i].to])
19 {
20 dis[e[i].to]=dis[u]+1;
21 if (e[i].to==t) return 1;
22 Q.push(e[i].to);
23 }
24 }
25 return 0;
26 }
27 int dfs(int x,int mx)
28 {
29 if (x==t||!mx) return mx;
30 int r=0;
31 for (int &i=cur[x];i;i=e[i].from)
32 if (e[i].v&&dis[e[i].to]==dis[x]+1)
33 {
34 int k=dfs(e[i].to,min(e[i].v,mx-r));
35 e[i].v-=k;
36 if (i&1) e[i+1].v+=k; else e[i-1].v+=k;
37 r+=k;
38 if (r==mx) break;
39 }
40 return r;
41 }
42 void dinic()
43 {
44 while (bfs())
45 {
46 for (int i=s;i<=t;i++) cur[i]=head[i];
47 ans+=dfs(s,inf);
48 }
49 }
50 int main()
51 {
52 scanf("%d%d%d",&n,&m,&num);
53 for (int i=1,x,y;i<=num;i++)
54 {
55 scanf("%d%d",&x,&y);
56 if (x<=n&&y<=m) insert(x,y+n,1),insert(y+n,x,0);
57 }
58 for (int i=1;i<=n;i++) insert(0,i,1),insert(i,0,0);
59 for (int i=1;i<=m;i++) insert(n+i,n+m+1,1),insert(n+m+1,n+i,0);
60 s=0,t=n+m+1,dinic();
61 printf("%d",ans);
62 }
代码2
1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 using namespace std;
5 int n,m,num,ans,cnt,head[1010],p[1010];
6 bool a[1010][1010],visit[1010];
7 int xyl(int x)
8 {
9 for (int i=1;i<=n;i++)
10 if (a[x][i]==true&&visit[i]==0)
11 {
12 visit[i]=1;
13 if (p[i]==0||xyl(p[i]))
14 {
15 p[i]=x;
16 return 1;
17 }
18 }
19 return 0;
20 }
21 int main()
22 {
23 scanf("%d%d%d",&n,&m,&num);
24 for (int i=1,x,y;i<=num;i++)
25 {
26 scanf("%d%d",&x,&y);
27 if (x<=n&&y<=m) a[x][y]=1;
28 }
29 for (int i=1;i<=n;i++) memset(visit,0,sizeof(visit)),ans+=xyl(i);
30 printf("%d",ans);
31 }
来源:https://www.cnblogs.com/Comfortable/p/9805101.html