[最大流][匈牙利算法] 洛谷 P3386 二分图匹配

题目描述

给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数

输入输出格式

输入格式:

第一行,n,m,e

第二至e+1行,每行两个正整数u,v,表示u,v有一条连边

输出格式:

共一行,二分图最大匹配

输入输出样例

输入样例#1:
1 1 1
1 1
输出样例#1:
1

说明

n,m leq 1000n,m1000, 1 leq u leq n1un, 1 leq v leq m1vm

因为数据有坑,可能会遇到 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