hdu1669+二分多重匹配+二分

n个人分成m组,求人数最多的那一组人数的最小值。

每个人肯定只能匹配一个组,但一个组可以匹配多个人,因此属于多重匹配。

我们设置一个limit,表示每组最多能容纳的人数。在dfs(u)寻找u的匹配时,如果某一组vv的人数小于limit,那么可以把u和vv匹配,vv已经匹配的人数+1。否则,当人数已经达到limit,我们对vv的每个匹配做dfs,即寻找增广,若能找到,修改这个匹配,即让vv和u匹配。

然后我们可以二分limit,当u集合(人的集合)中所有点都能找到匹配,则减小limit值,否则只要有一个点找不到匹配,增大limit值。

多重匹配和二分匹配匈牙利算法的写法类似,只不过加了一个cnt数组表示v已经匹配到的人数,linker数组也增加了一维。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 using namespace std;
 5 int n,m;
 6 vector<int> v[1100];
 7 int linker[1100][1100],vis[1100],cnt[1100];
 8 int limit;
 9 bool dfs(int u)
10 {
11     int i,j;
12     for(i=0;i<v[u].size();i++)
13     {
14         int vv=v[u][i];
15         if(!vis[vv])
16         {
17             vis[vv]=1;
18             if(cnt[vv]<limit)
19             {
20                 linker[vv][cnt[vv]++]=u;
21                 return true;
22             }
23             else
24             {
25                 for(j=0;j<cnt[vv];j++)
26                 {
27                     if(dfs(linker[vv][j]))
28                     {
29                         linker[vv][j]=u;
30                         return true;
31                     }
32                 }
33             }
34         }
35     }
36     return false;
37 }
38 int main()
39 {
40     int i,j;
41     char str[110000];
42     while(scanf("%d%d",&n,&m)!=EOF)
43     {
44         getchar();
45         if(n==0&&m==0) break;
46         for(i=0;i<n;i++)
47             v[i].clear();
48         for(i=0;i<n;i++)
49         {
50             gets(str);
51             int len=strlen(str);
52             j=0;
53             loop:for(;j<len;j++)
54             {
55                 if(str[j]>='0'&&str[j]<='9')
56                     break;
57             }
58             int num=0;
59             bool judge=false;
60             for(;j<len;j++)
61             {
62                 if(str[j]>='0'&&str[j]<='9')
63                 {
64                     judge=true;
65                     num=num*10+(str[j]-'0');
66                 }
67                 else break;
68             }
69             if(judge) v[i].push_back(num);
70             if(j<len) goto loop;
71         }
72         int l=0,r=n;
73         while(l<r)
74         {
75             limit=(l+r)/2;
76             memset(cnt,0,sizeof(cnt));
77             for(i=0;i<n;i++)
78             {
79                 memset(vis,0,sizeof(vis));
80                 if(!dfs(i)) break;
81             }
82             if(i>=n) r=limit;
83             else l=limit+1;
84         }
85         printf("%d
",l);
86     }
87     return 0;
88 }
原文地址:https://www.cnblogs.com/mt522/p/5372791.html