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

设二分值为X,判断是否在小于X的值以内,是否有可行解。以此进行二分。

建图,要限流,就是每个点都单独建一条边X到汇点,看是否满流。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define INF 1e9
using namespace std;
const int maxn=1500+5; struct Edge
{
int from,to,cap,flow;
Edge(){}
Edge(int f,int t,int c,int fl):from(f),to(t),cap(c),flow(fl){}
}; struct Dinic
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
int d[maxn];
int cur[maxn];
bool vis[maxn]; void init(int n,int s,int t)
{
this->n=n, this->s=s, this->t=t;
edges.clear();
for(int i=0;i<n;i++) G[i].clear();
} void AddEdge(int from,int to,int cap)
{
edges.push_back( Edge(from,to,cap,0) );
edges.push_back( Edge(to,from,0,0) );
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
} bool BFS()
{
queue<int> Q;
memset(vis,0,sizeof(vis));
vis[s]=true;
d[s]=0;
Q.push(s);
while(!Q.empty())
{
int x=Q.front(); Q.pop();
for(int i=0;i<G[x].size();++i)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to] && e.cap>e.flow)
{
vis[e.to]=true;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
} int DFS(int x,int a)
{
if(x==t || a==0) return a;
int flow=0,f;
for(int& i=cur[x];i<G[x].size();++i)
{
Edge& e=edges[G[x][i]];
if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
{
e.flow +=f;
edges[G[x][i]^1].flow -=f;
flow +=f;
a -=f;
if(a==0) break;
}
}
return flow;
} int max_flow()
{
int ans=0;
while(BFS())
{
memset(cur,0,sizeof(cur));
ans +=DFS(s,INF);
}
return ans;
}
}DC; int n,m;
vector<int> g[maxn];//g[i]中保存第i个人可被分到的组编号
bool solve(int limit)
{
int src=0, dst=n+m+1;
DC.init(2+n+m,src,dst);
for(int i=1;i<=n;i++) DC.AddEdge(src,i,1);
for(int i=1;i<=m;i++) DC.AddEdge(n+i,dst,limit);
for(int i=1;i<=n;i++)
for(int j=0;j<g[i].size();++j)
DC.AddEdge(i,g[i][j],1);
return DC.max_flow() == n;
} int main()
{
while(scanf("%d%d",&n,&m)==2)
{
if(n==0 && m==0) break;
for(int i=1;i<=n;i++) g[i].clear();
for(int i=1;i<=n;i++)
{
char str[100];
scanf("%s",str);
while(1)
{
int x;
scanf("%d",&x);
g[i].push_back(x+1+n);//注意这里压入的已经是处理后的编号了
char ch=getchar();
if(ch=='\n') break;
}
}
int L=0,R=n;
while(R>L)
{
int mid=L+(R-L)/2;
if(solve(mid)) R=mid;
else L=mid+1;
}
printf("%d\n",R);
}
return 0;
}

图论--网络流--最大流 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【二分+最大流】【二分图多重匹配问题】

    题目链接:http://poj.org/problem?id=2289 Jamie's Contact Groups Time Limit: 7000MS   Memory Limit: 65536K ...

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

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

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

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

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

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

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

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

  9. POJ 2289 Jamie's Contact Groups

    二分答案+网络最大流 #include<cstdio> #include<cstring> #include<cmath> #include<vector&g ...

随机推荐

  1. MTK Android 耳机线控的实现方法

    android 耳机线控的实现方法 keycodeonkeydownkeyevent 耳机线控的功能 耳机线控是一种很好用,并且能提升用户体验的功能.可以用来实现一些常用和基本的功能.比如:实现音乐播 ...

  2. 将class 编译后文件内容输入到 文本文件中的命令

    javap -c InnerTest$1 > InnerTest$1.txt

  3. 【python系统学习14】类的继承与创新

    目录: 目录: [toc] 类的继承 子类和父类 继承的写法 继承示例 父类可以被无限个子类所继承 子类实例可调用父类属性和方法 类的始祖(根类) 根类 - object 实例归属判断 - isins ...

  4. day23作业

    # 作业: # 1.把登录与注册的密码都换成密文形式 info = {"tom":"202cb962ac59075b964b07152d234b70"} def ...

  5. Websocket直播间聊天室教程 - GoEasy快速实现聊天室

    最近两年直播那个火啊,真的是无法形容!经常有朋友问起,我想实现一个直播间聊天或者我想开发一个聊天室, 要如何开始呢? 今天小编就手把手的教你用GoEasy做一个聊天室,当然也可以用于直播间内的互动.全 ...

  6. 微信小程序 —搜索框

    wxSearch优雅的微信小程序搜索框 一.功能 支持自定义热门key 支持搜索历史 支持搜索建议 支持搜索历史(记录)缓存 二.使用 1.将wxSearch文件夹整个拷贝到根目录下 2.引入 // ...

  7. Java中什么是构造方法

    this(...)本类的构造方法super(...)父类的构造方法构造方法:给对象的数据进行初始化格式:A:方法名与类名相同B:没有返回值类型,连void都没有C:没有具体的返回值注意事项:A:如果我 ...

  8. 设计模式 - 命令模式详解及其在JdbcTemplate中的应用

    基本介绍 在软件设计中,我们经常需要向某些对象发送一些请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需要在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来设计,使得 ...

  9. <string>头文件常用成员函数

    之前说过 string和vector一样,也是一种顺序容器,并且它也自带成员函数,用法和vector的成员函数差不多,不过它只能用来存放字符,也就是字符串. 在c++中,<string>基 ...

  10. urlencode()和rawurlencode()区别

    urlencode和rawurlencode两个方法在处理字母数字,特殊符号,中文的时候结果都是一样的 ,唯一的不同是对空格的处理,   urlencode处理成“+”,    rawurlencod ...