二分图多重匹配

在二分图的最大匹配中,每个点(不管是X集合还是Y集合)最多只能与一条匹配边相关联,

然而,经常有这种问题,即二分图的一个点可以和多条匹配边相关联,但有上限,即cap[i]表示点i最多能和cap[i]条匹配边相关联。

hdu 3605

题意:2012来了,n个人可以逃往m个星球中的k个,每个星球都有上限,问所有的人能不能都都逃亡成功;

 1 #include <stdio.h>
 2 #include <string.h>
 3 const int N = 100000 + 10;
 4 const int M = 10 + 10;
 5 int n,m;
 6 int Map[N][M];
 7 int cap[M];//星球i的容量上限
 8 int cy[M][N];
 9 int num[M];//num[i]记录星球i已经匹配了n个人
10 bool vis[M];
11 
12 
13 bool dfs(int u)
14 {
15     for(int i=0; i<m; ++i)
16     {
17         if(!vis[i] && Map[u][i])
18         {
19             vis[i] = true;
20             if(num[i] < cap[i])
21             {
22                 cy[i][num[i]++] = u;
23                 return true;
24             }
25             else
26             {
27                 for(int j=0; j<cap[i]; ++j)//寻找增广路,可以从u出发,经过n条匹配边中的一条找到增广路就行
28                 {
29                     if(dfs(cy[i][j]))
30                     {
31                         cy[i][j] = u;
32                         return true;
33                     }
34                 }
35             }
36         }
37     }
38     return false;
39 }
40 bool MulMatch()
41 {
42     memset(num, 0, sizeof(num));
43     for(int i=0; i<n; ++i)
44     {
45         memset(vis, 0, sizeof(vis));
46         if(!dfs(i))
47             return false;
48     }
49     return true;
50 }
51 int main()
52 {    
53     int i,j;
54     while(scanf("%d%d",&n,&m)!=EOF)
55     {
56         for(i=0; i<n; ++i)
57             for(j=0; j<m; ++j)
58                 scanf("%d",&Map[i][j]);
59         
60         for(i=0; i<m; ++i)
61             scanf("%d",&cap[i]);
62         printf("%s
",MulMatch()?"YES":"NO");
63     }
64     
65     return 0;
66 }

 hdu 1669

题意:给定n个人,m个组,没个人适合m个组中的k个,由给定的数据说明,
要求分组后,人最多的那个组是所有可能情况中最小的

组的人数的情况可能是0--->n  ,但是一个一个枚举太耗时了,所以用二分枚举最大组的容量上限,剩下的代码就都和上面那题一样

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 using namespace std;
 5 const int nMax = 1000 + 10;
 6 const int mMax = 555 + 10;
 7 int num[mMax];
 8 bool vis[mMax];
 9 int cy[mMax][nMax];
10 vector<int> G[nMax];
11 int n,m,limit;
12 
13 void init()
14 {
15     for(int i=0; i<n; ++i)
16         G[i].clear();
17 }
18 bool dfs(int u)
19 {
20     for(int i=0; i<G[u].size(); ++i)
21     {
22         int v = G[u][i];
23         if(!vis[v])
24         {
25             vis[v] = true;
26             if(num[v] < limit)
27             {
28                 cy[v][num[v]++] = u;
29                 return true;
30             }
31             for(int j=0; j<limit; ++j)
32                 if(dfs(cy[v][j]))
33                 {
34                     cy[v][j] = u;
35                     return true;
36                 }
37             
38         }
39     }
40     return false;
41 }
42 bool MulMatch()
43 {
44     memset(num, 0, sizeof(num));
45     memset(cy, 0, sizeof(cy));
46     for(int i=0; i<n; ++i)
47     {
48         memset(vis, 0, sizeof(vis));
49         if(!dfs(i))
50             return false;
51     }
52     return true;
53 }
54 int main()
55 {
56     char str[20];
57     int i,j;
58     while(true)
59     {
60         scanf("%d%d",&n,&m);
61         if(n==0 && m==0)
62             break;
63         init();
64         for(i=0; i<n; ++i)
65         {
66             scanf("%s",str);
67             while( getchar()==' ')
68             {
69                 scanf("%d",&j);
70                 G[i].push_back(j);
71             }
72         }
73         int low = 0, high = n,ans = 0;
74         while(low <= high)
75         {
76             limit = (low + high) >> 1;//二分枚举最大组的容量上限为limit
77             if(MulMatch())
78             {
79                 ans = limit;
80                 high = limit - 1;
81             }
82             else
83                 low = limit + 1;
84         }
85         printf("%d
",ans);
86     }
87     return 0;
88 }
原文地址:https://www.cnblogs.com/justPassBy/p/4025031.html