Jamie's Contact Groups
Time Limit: 7000MS   Memory Limit: 65536K
Total Submissions: 8473   Accepted: 2875

Description

Jamie is a very popular girl and has quite a lot of friends, so she always keeps a very long contact list in her cell phone. The contact list has become so long that it often takes a long time for her to browse through the whole list to find a friend's number. As Jamie's best friend and a programming genius, you suggest that she group the contact list and minimize the size of the largest group, so that it will be easier for her to search for a friend's number among the groups. Jamie takes your advice and gives you her entire contact list containing her friends' names, the number of groups she wishes to have and what groups every friend could belong to. Your task is to write a program that takes the list and organizes it into groups such that each friend appears in only one of those groups and the size of the largest group is minimized.

Input

There will be at most 20 test cases. Ease case starts with a line containing two integers N and M. where N is the length of the contact list and M is the number of groups. N lines then follow. Each line contains a friend's name and the groups the friend could belong to. You can assume N is no more than 1000 and M is no more than 500. The names will contain alphabet letters only and will be no longer than 15 characters. No two friends have the same name. The group label is an integer between 0 and M - 1. After the last test case, there is a single line `0 0' that terminates the input.

Output

For each test case, output a line containing a single integer, the size of the largest contact group.

Sample Input

  1. 3 2
  2. John 0 1
  3. Rose 1
  4. Mary 1
  5. 5 4
  6. ACM 1 2 3
  7. ICPC 0 1
  8. Asian 0 2 3
  9. Regional 1 2
  10. ShangHai 0 2
  11. 0 0

Sample Output

  1. 2
  2. 2

Source

题意:
  N个人,M个组,给出每个人可以考虑选择的组号,要求每个人都必须选且只能选一个组,求一个划分方案使得最多人数的组的人数 是所有方案中人数最少的,结果输出这个最小值。

题解:

  一对多的二分图多重匹配问题。网络流建图:源点到每个人连边,边权为1;每个人到可以考虑选择的组连边,边权为1;每个组到汇点连边,边权为求解的最小值。这个最小值很明显可以想到二分求解。

代码:

  1. #include <cstdio>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <queue>
  5. #include <cstring>
  6. using namespace std;
  7. const int N = ;
  8. const int M = 1e6;
  9. const int inf = 1e9;
  10. int n, m, S, T;
  11. int dep[N], cur[N];
  12. int head[N];
  13. struct Edge{
  14. int v, c, nex;
  15. Edge(int _v=,int _c=,int _nex=):v(_v),c(_c),nex(_nex){}
  16. }E[M];
  17.  
  18. int cnt;
  19. void add(int u, int v, int c){
  20. E[cnt].v = v;
  21. E[cnt].c = c;
  22. E[cnt].nex = head[u];
  23. head[u] = cnt++;
  24. }
  25.  
  26. bool bfs() {
  27. queue<int> q;
  28. memset(dep, -, sizeof(dep));
  29. q.push(S); dep[S] = ;
  30. while(!q.empty()) {
  31. int u = q.front(); q.pop();
  32. for(int i = head[u]; ~i; i = E[i].nex) {
  33. int v = E[i].v;
  34. if(E[i].c && dep[v] == -) {
  35. dep[v] = dep[u] + ;
  36. q.push(v);
  37. }
  38. }
  39. }
  40. return dep[T] != -;
  41. }
  42. int dfs(int u, int flow) {
  43. if(u == T) return flow;
  44. int w, used=;
  45. for(int i = head[u]; ~i; i = E[i].nex) {
  46. int v = E[i].v;
  47. if(dep[v] == dep[u] + ) {
  48. w = flow - used;
  49. w = dfs(v, min(w, E[i].c));
  50. E[i].c -= w; E[i^].c += w;
  51. if(v) cur[u] = i;
  52. used += w;
  53. if(used == flow) return flow;
  54. }
  55. }
  56. if(!used) dep[u] = -;
  57. return used;
  58. }
  59. int dinic() {
  60. int ans = ;
  61. while(bfs()) {
  62. for(int i = ; i <= T;i++)
  63. cur[i] = head[i];
  64. ans += dfs(S, inf);
  65. }
  66. return ans;
  67. }
  68. int main() {
  69. char s[];
  70. int i, j, x, t;
  71. while(~scanf("%d%d", &n, &m),n+m) {
  72. memset(head, -, sizeof(head));
  73. cnt = ;
  74. S = n+m+; T = n+m+;
  75. vector<int>g[N];
  76. for(i = ; i <= n; ++i) g[i].clear();
  77. for(i = ; i < n; ++i) {
  78. scanf("%s", s);
  79. while(getchar() != '\n') {
  80. scanf("%d", &x);
  81. g[i].push_back(x);
  82. }
  83. }
  84. int l = , r = n, mid;
  85. while(l <= r) {
  86. memset(head, -, sizeof(head));
  87. cnt = ;
  88. mid = (l+r)/;
  89. for(i = ; i < n; ++i) {
  90. for(j = ; j < g[i].size(); ++j)
  91. add(i, n+g[i][j], ),add(n+g[i][j], i, );
  92. }
  93. for(i = ; i < n; ++i) add(S,i,), add(i,S,);
  94. for(i = n; i < n+m; ++i) add(i,T,mid),add(T,i,);
  95. t = dinic();
  96. if(t == n) r = mid - ;
  97. else l = mid + ;
  98. }
  99. printf("%d\n", l);
  100. }
  101. }

485ms

poj 2289 Jamie's Contact Groups【二分+最大流】【二分图多重匹配问题】的更多相关文章

  1. POJ 2289 Jamie's Contact Groups (二分+最大流)

    题目大意: 有n个人,可以分成m个组,现在给出你每个人可以去的组的编号,求分成的m组中人数最多的组最少可以有多少人. 算法讨论: 首先喷一下这题的输入,太恶心了. 然后说算法:最多的最少,二分的字眼. ...

  2. Poj 2289 Jamie's Contact Groups (二分+二分图多重匹配)

    题目链接: Poj 2289 Jamie's Contact Groups 题目描述: 给出n个人的名单和每个人可以被分到的组,问将n个人分到m个组内,并且人数最多的组人数要尽量少,问人数最多的组有多 ...

  3. POJ 2289 Jamie's Contact Groups / UVA 1345 Jamie's Contact Groups / ZOJ 2399 Jamie's Contact Groups / HDU 1699 Jamie's Contact Groups / SCU 1996 Jamie's Contact Groups (二分,二分图匹配)

    POJ 2289 Jamie's Contact Groups / UVA 1345 Jamie's Contact Groups / ZOJ 2399 Jamie's Contact Groups ...

  4. POJ 2289——Jamie's Contact Groups——————【多重匹配、二分枚举匹配次数】

    Jamie's Contact Groups Time Limit:7000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I ...

  5. POJ 2289 Jamie's Contact Groups 二分图多重匹配 难度:1

    Jamie's Contact Groups Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 6511   Accepted: ...

  6. POJ 2289 Jamie's Contact Groups(多重匹配+二分)

    题意: Jamie有很多联系人,但是很不方便管理,他想把这些联系人分成组,已知这些联系人可以被分到哪个组中去,而且要求每个组的联系人上限最小,即有一整数k,使每个组的联系人数都不大于k,问这个k最小是 ...

  7. POJ 2289 Jamie's Contact Groups 【二分】+【多重匹配】(模板题)

    <题目链接> 题目大意: 有n个人,每个人都有一个或者几个能够归属的分类,将这些人分类到他们能够归属的分类中后,使所含人数最多的分类值最小,求出该分类的所含人数值. 解题分析: 看到求最大 ...

  8. POJ 2289 Jamie's Contact Groups & POJ3189 Steady Cow Assignment

    这两道题目都是多重二分匹配+枚举的做法,或者可以用网络流,实际上二分匹配也就实质是网络流,通过枚举区间,然后建立相应的图,判断该区间是否符合要求,并进一步缩小范围,直到求出解.不同之处在对是否满足条件 ...

  9. POJ - 2289 Jamie's Contact Groups (二分图多重匹配)

    题意:N个人,M个团体.每个人有属于自己的一些团体编号.将每个人分配到自己属于的团体中,问这个人数最多的团体其人数最小值是多少. 分析:一个一对多的二分图匹配,且是最大值最小化问题.二分图的多重匹配建 ...

随机推荐

  1. WebApi使用swagger ui自动生成接口文档

    之前就写到.最近正在使用webapi.这里介绍一个实用的东西swageer ui现在开发都是前后端分开.我们这里是给前端提供api.有时候对于一个api的描述,并不想专门写一份文档.很浪费时间.swa ...

  2. Django(三):HttpRequest和HttpResponse

    当一个请求连接进来时,django会创建一个HttpRequest对象来封装和保存所有请求相关的信息,并且会根据请求路由载入匹配的视图函数.每个请求的视图函数都会返回一个HttpResponse. H ...

  3. TortoiseGit用户手册

    3 配置TortoiseGit 3.1 生成公钥 生成SSH安全密钥,提供给GIT版本库管理员以访问Git 版本库,点击桌面上生成的图标 然后执行执行“ssh-keygen”生成自己的公钥: 一路回车 ...

  4. MySQL中文编码设置为utf-8

    MySQL中文编码设置为utf-8 原文地址:http://blog.csdn.net/wangnan537/article/details/47819167 1. 查看MySQL数据库的默认编码有如 ...

  5. Docker for Windows(五)实践搭建SqlServer服务&执行数据库操作

    上一篇我们已经搭建了一个mysql数据库服务了:Docker for Windows(四)实践搭建&删除MySQL服务,发现用Docker确实是方便且容易,但上一篇主要是服务的搭建删除等基础操 ...

  6. http常见状态码有哪些?

    ajax常见面试题 1:什么是ajax?ajax作用是什么? 异步的javascript和xml AJAX 是一种用于创建快速动态网页的技术. ajax用来与后台交互 2:原生js ajax请求有几个 ...

  7. 多张报表导出到一个多sheet页excel

     业务需求: 通过勾选不同的报表名称,然后直接执行导出excel.并且这些报表需要统一导入到一个excel的多个sheet页中,并且对某些报表可能需要增加一些类似'已审核'之类的图片(展现时并没有 ...

  8. RadioGroup实现类似ios的分段选择(UISegmentedControl)控件

    在ios7中有一种扁平风格的控件叫做分段选择控件UISegmentedControl,控件分为一排,横放着几个被简单线条隔开的按钮,每次点击只能选择其中一个按钮,他类似于tabbar但是又稍微有点区别 ...

  9. shiro web 集成

    集成方法 shiro与web集成,主要是通过配置一个ShiroFilter拦截所有URL,其中ShiroFilter类似于SpringMVC的前端控制器,是所有请求入口点,负责根据配置(如ini配置文 ...

  10. java 标准输出流、标准错误输出流、标准输入流及扫描仪

    初步认识标准输出流.错误输出流.输入流.扫描仪 package com.mydemo.controller; import java.util.Scanner; public class HelloW ...