二分图多重匹配

在二分图的最大匹配中,每个点(不管是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\n",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\n",ans);
86     }
87     return 0;
88 }
时间: 2024-11-05 14:48:14

二分图多重匹配的相关文章

hihoCoder 1393 网络流三&#183;二分图多重匹配(Dinic求二分图最大多重匹配)

#1393 : 网络流三·二分图多重匹配 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 学校的秋季运动会即将开始,为了决定参赛人员,各个班又开始忙碌起来. 小Hi和小Ho作为班上的班干部,统计分配比赛选手的重任也自然交到了他们手上. 已知小Hi和小Ho所在的班级一共有N名学生(包含小Hi和小Ho),编号依次为1..N. 运动会一共有M项不同的比赛,编号为1..M.第i项比赛每个班需要派出m[i]名选手参加. 根据小Hi和小Ho的统计,编号为i的学生表示最多同时参加

hiho 第117周 二分图多重匹配,网络流解决

描述 学校的秋季运动会即将开始,为了决定参赛人员,各个班又开始忙碌起来. 小Hi和小Ho作为班上的班干部,统计分配比赛选手的重任也自然交到了他们手上. 已知小Hi和小Ho所在的班级一共有N名学生(包含小Hi和小Ho),编号依次为1..N. 运动会一共有M项不同的比赛,编号为1..M.第i项比赛每个班需要派出m[i]名选手参加. 根据小Hi和小Ho的统计,编号为i的学生表示最多同时参加a[i]项比赛,并且给出他所擅长的b[i]项比赛的编号. 小Hi和小Ho希望将每个学生都安排到他所擅长的比赛项目,

kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树

二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图. 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数.如果你还不知道什么是最小点覆盖,我也在这里说一下:假如选

HDU 3605 Escape(二分图多重匹配问题)

Escape Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 10382    Accepted Submission(s): 2485 Problem Description 2012 If this is the end of the world how to do? I do not know how. But now scient

POJ 2289 Jamie&#39;s Contact Groups 二分图多重匹配

题意:n个人,m个组,给出每个人可以分到那些组中,把每个人都分进某组中,问最大组的人数最小为?n<=1e3,m<=500,二分图多重匹配 左边为人 右边为分组 可以多个人对一个组由于要求最大组的最小人数 二分答案x,右边点最多流量为x,判断匹配数是否n即可. #include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long ll; t

HDU 3605 Escape【二分图多重匹配】

题意: 有n个人去m个星球  告诉你每个人想去哪些星球和每个星球最多容纳多少人,问能不能让所有人都满足 分析: 二分图多重匹配 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 7 const int maxn = 100005; 8 const int maxm = 15; 9 10

Poj 2289 Jamie&#39;s Contact Groups (二分+二分图多重匹配)

题目链接: Poj 2289 Jamie's Contact Groups 题目描述: 给出n个人的名单和每个人可以被分到的组,问将n个人分到m个组内,并且人数最多的组人数要尽量少,问人数最多的组有多少人? 解题思路: 二分图多重匹配相对于二分匹配来说不再是节点间的一一对应,而是Xi可以对应多个Yi.所以我们就需要一个限制(Xi最多匹配几个Yi).当Yi需要匹配Xi的时候,Xi的匹配未到上限,直接匹配,否则进行增广路.其实是二分图多重匹配的模板题,再套一个二分枚举最多组的人数就OK咯.下面就上板

hdu 3605 Escape (二分图多重匹配)

Escape Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4298    Accepted Submission(s): 1129 Problem Description 2012 If this is the end of the world how to do? I do not know how. But now scient

二分图多重匹配问题

二分图多重匹配问题 #include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 100005; const int maxm = 15; int cap[maxm]; int Link[maxm][maxn]; int vLink[maxm]; int mat[maxn][maxm]; int

POJ2289 Jamie&#39;s Contact Groups(二分图多重匹配)

题意: 给定一个规模为n的名单,要将名单中的人归到m个组中,给出每个人可能的分组号,需要确定一种分配方案,使得最大规模的组最小. 思路: 二分图多重匹配 如果所到的组没满,就去那个组 如果满了,就从那个组里踢出一个 如果能踢出来,就把那个踢出来,把当前的放进去 如果所有能到的组都踢不出来,就不对了 至于那个最大规模的具体值,二分一下就OK了 /* *********************************************** Author :devil Created Time