首页 > 代码库 > 二分图多重匹配

二分图多重匹配

 

在二分图的最大匹配中,每个点(不管是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             else26             {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;//二分枚举最大组的容量上限为limit77             if(MulMatch())78             {79                 ans = limit;80                 high = limit - 1;81             }82             else83                 low = limit + 1;84         }85         printf("%d\n",ans);86     }87     return 0;88 }

 

二分图多重匹配