题目链接:https://vjudge.net/problem/POJ-2289

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

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

3 2
John 0 1
Rose 1
Mary 1
5 4
ACM 1 2 3
ICPC 0 1
Asian 0 2 3
Regional 1 2
ShangHai 0 2
0 0

Sample Output

2
2

Source

题解:

题意:jamie的QQ有n个联系人,且设置了m个分组,规定了哪些朋友可以去哪些分组。为了能够快速地找到朋友,jamie希望人数最多的分组的人数最少(最大值最小),并且满足每个朋友仅存在于一个分组中。

1.二分最大值,即每个分组的容量。

2.利用二分图多重匹配,或者最大流,求出是否所有人都可以归到一个分组中。如果可以,则减小容量,否则增大容量。

多重匹配:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
const int INF = 2e9;
const int MOD = 1e9+;
const int MAXM = 5e2+;
const int MAXN = 1e3+; int uN, vN;
int num[MAXM], linker[MAXM][MAXN];
bool g[MAXN][MAXM], used[MAXM]; bool dfs(int u)
{
for(int v = ; v<vN; v++)
if(g[u][v] && !used[v])
{
used[v] = true;
if(linker[v][]<num[v])
{
linker[v][++linker[v][]] = u;
return true;
}
for(int i = ; i<=num[v]; i++)
if(dfs(linker[v][i]))
{
linker[v][i] = u;
return true;
}
}
return false;
} bool hungary(int mid)
{
for(int i = ; i<vN; i++)
{
num[i] = mid;
linker[i][] = ;
}
for(int u = ; u<uN; u++)
{
memset(used, false, sizeof(used));
if(!dfs(u)) return false;
}
return true;
} char tmp[];
int main()
{
while(scanf("%d%d", &uN, &vN) && (uN||vN))
{
memset(g, false, sizeof(g));
getchar();
for(int i = ; i<uN; i++)
{
gets(tmp);
int j = , len = strlen(tmp);
while(tmp[j]!=' ' && j<len) j++;
j++;
for(int v = ; j<=len; j++)
{
if(tmp[j]==' '||j==len)
{
g[i][v] = true;
v = ;
}
else v = v*+(tmp[j]-'');
}
} int l = , r = uN;
while(l<=r)
{
int mid = (l+r)>>;
if(hungary(mid))
r = mid - ;
else
l = mid + ;
}
printf("%d\n", l);
}
}

最大流:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
const int INF = 2e9;
const int MOD = 1e9+;
const int MAXM = 5e2+;
const int MAXN = 2e3+; struct Edge
{
int to, next, cap, flow;
}edge[MAXN*MAXN];
int tot, head[MAXN]; int uN, vN, maze[MAXN][MAXN];
int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN]; void add(int u, int v, int w)
{
edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = ;
edge[tot].next = head[u]; head[u] = tot++;
edge[tot].to = u; edge[tot].cap = ; edge[tot].flow = ;
edge[tot].next = head[v]; head[v] = tot++;
} int sap(int start, int end, int nodenum)
{
memset(dep, , sizeof(dep));
memset(gap, , sizeof(gap));
memcpy(cur, head, sizeof(head));
int u = pre[start] = start, maxflow = ,aug = INF;
gap[] = nodenum;
while(dep[start]<nodenum)
{
loop:
for(int i = cur[u]; i!=-; i = edge[i].next)
{
int v = edge[i].to;
if(edge[i].cap-edge[i].flow && dep[u]==dep[v]+)
{
aug = min(aug, edge[i].cap-edge[i].flow);
pre[v] = u;
cur[u] = i;
u = v;
if(v==end)
{
maxflow += aug;
for(u = pre[u]; v!=start; v = u,u = pre[u])
{
edge[cur[u]].flow += aug;
edge[cur[u]^].flow -= aug;
}
aug = INF;
}
goto loop;
}
}
int mindis = nodenum;
for(int i = head[u]; i!=-; i = edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap-edge[i].flow && mindis>dep[v])
{
cur[u] = i;
mindis = dep[v];
}
}
if((--gap[dep[u]])==)break;
gap[dep[u]=mindis+]++;
u = pre[u];
}
return maxflow;
} bool test(int mid)
{
tot = ;
memset(head, -, sizeof(head));
for(int i = ; i<uN; i++)
{
add(uN+vN, i, );
for(int j = ; j<vN; j++)
if(maze[i][j])
add(i, uN+j, );
}
for(int i = ; i<vN; i++)
add(uN+i, uN+vN+, mid); int maxflow = sap(uN+vN, uN+vN+, uN+vN+);
return maxflow == uN;
} char tmp[];
int main()
{
while(scanf("%d%d", &uN, &vN) && (uN||vN))
{
memset(maze, , sizeof(maze));
getchar();
for(int i = ; i<uN; i++)
{
gets(tmp);
int j = , len = strlen(tmp);
while(tmp[j]!=' ' && j<len) j++;
j++;
for(int v = ; j<=len; j++)
{
if(tmp[j]==' '||j==len)
{
maze[i][v] = ;
v = ;
}
else v = v*+(tmp[j]-'');
}
} int l = , r = uN;
while(l<=r)
{
int mid = (l+r)>>;
if(test(mid))
r = mid - ;
else
l = mid + ;
}
printf("%d\n", l);
}
}

POJ2289 Jamie's Contact Groups —— 二分图多重匹配/最大流 + 二分的更多相关文章

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

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

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

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

  3. POJ3189 Steady Cow Assignment —— 二分图多重匹配/最大流 + 二分

    题目链接:https://vjudge.net/problem/POJ-3189 Steady Cow Assignment Time Limit: 1000MS   Memory Limit: 65 ...

  4. POJ2112 Optimal Milking —— 二分图多重匹配/最大流 + 二分

    题目链接:https://vjudge.net/problem/POJ-2112 Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K T ...

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

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

  6. HDU 1669 Jamie's Contact Groups(多重匹配+二分枚举)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1669 题目大意: 给你各个人可以属于的组,把这些人分组,使这些组中人数最多的组人数最少,并输出这个人数 ...

  7. POJ2289 Jamie's Contact Groups(二分图多重匹配)

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

  8. hdu3605 Escape 二分图多重匹配/最大流

    2012 If this is the end of the world how to do? I do not know how. But now scientists have found tha ...

  9. Jamie's Contact Groups---hdu1669--poj2289(多重匹配+二分)

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

随机推荐

  1. HDU1166-敌兵布阵,线段数模板题~~

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  2. 售货员的难题(codevs 2596)

    题目描述 Description 某乡有n个村庄(1<n<=15),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村 ...

  3. 背包!背包!HDU 2602 Bone Collector + HDU 1114 Piggy-Bank + HDU 2191 512

    http://acm.hdu.edu.cn/showproblem.php?pid=2602 第一题 01背包问题 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  4. 【HDOJ6299】Balanced Sequence(贪心)

    题意:给定n个只有左右括号的序列,要求将它们重新排序使得匹配的括号对数最大. n<=1e5 s[i]<=1e5 sum s[i]<=5e6 思路: 先把每个串内部的匹配数量减去,剩下 ...

  5. 会修修的莫队--BZOJ2120: 数颜色

    $n \leq 10000$的数列,$m \leq 10000$个操作,一:单点修改:二:查区间不同数字个数.修改数$\leq 1000$,数字$\leq 1000000$. 我不会告诉您这是三种写法 ...

  6. 汕头市赛srm10 T2

    n个数,分组,数Ai要在至少含有Ai个数的组,求最多分多少组. 方法一:大的数应该尽量跟大的在一起,这样才能让小的出现很多很多组,所以从大到小排序,给当前序列中最大的数x分x个数.代码如下: #inc ...

  7. 1597: [Usaco2008 Mar]土地购买 [ dp+斜率优化 ] 未完

    传送门 1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1979  Solved: 705[Subm ...

  8. hdu 1429 bfs+二进制状态压缩

    开始时候只用了BFS,显然超时啊,必然在结构体里加一个数组什么的判重啊,开始用的一个BOOL数组,显然还是不行,复杂度高,每次都要遍历数组来判重:后百度之,学习了二进制状态压缩,其实就用一个二进制数来 ...

  9. Swift--错误集:couldn’t be opened because you don’t have permission to view it

    bug复现过程  把snapkit拉入代码中时,也把里面的info.plist文件拖到项目中,运行时,提示“couldn’t be opened because you don’t have perm ...

  10. List和Map、Set的区别

    首先 List 和 Set 是存储单列数据的集合,Map 是存储键和值这样的双列数据的集合:List 中存储的数据是有顺序,并且允许重复:Map 中存储的数据是没有顺序的,其键是不能重复的,它的值是可 ...