题目大意:

有n个人,可以分成m个组,现在给出你每个人可以去的组的编号,求分成的m组中人数最多的组最少可以有多少人。

算法讨论:

首先喷一下这题的输入,太恶心了。

然后说算法:最多的最少,二分的字眼。二分什么,因为我们说的是组的人,所以要对组的流出量进行二分。其余的都连流量为1的边,然后对“小组”点的流出量二分连边,最后跑最大流判断

是否等于N即可。还是蛮简单的。

Codes:

 #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
using namespace std; struct Edge{
int from, to, cap, flow;
Edge(int _from=, int _to=, int _cap=, int _flow=):
from(_from), to(_to), cap(_cap), flow(_flow) {}
}E[ + ]; struct Dinic{
static const int N = + ;
static const int M = + ;
static const int oo = 0x3f3f3f3f; int n, m, s, t;
vector <Edge> edges;
vector <int> G[N];
int cur[N], dis[N];
bool vi[N]; void Clear(){
for(int i = ; i <= n; ++ i) G[i].clear();
edges.clear();
}
void Add(int from, int to, int cap, int flow){
edges.push_back((Edge){from, to, cap, });
edges.push_back((Edge){to, from, , });
int m = edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
}
bool bfs(){
memset(vi, false, sizeof vi);
dis[s] = ; vi[s] = true;
queue <int> q;
q.push(s);
while(!q.empty()){
int x = q.front(); q.pop();
for(int i = ; i < G[x].size(); ++ i){
Edge &e = edges[G[x][i]];
if(!vi[e.to] && e.cap > e.flow){
vi[e.to] = true;
dis[e.to] = dis[x] + ;
q.push(e.to);
}
}
}
return vi[t];
}
int dfs(int x, int a){
if(x == t || a == ) return a;
int flw = , f;
for(int &i = cur[x]; i < G[x].size(); ++ i){
Edge &e = edges[G[x][i]];
if(dis[x] + == dis[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > ){
e.flow += f; edges[G[x][i]^].flow -= f;
a -= f; flw += f;
if(a == ) break;
}
}
return flw;
}
int MaxFlow(int s, int t){
this->s = s; this->t = t;
int flw = ;
while(bfs()){
memset(cur, , sizeof cur);
flw += dfs(s, oo);
}
return flw;
}
}Net; int n, m;
char buf[];
int len, cnt = , x, np;
int bj[ + ];
int l, r, mid; bool check(int mv){
Net.Clear();
for(int i = ; i <= n; ++ i)
Net.Add(, i, , );
for(int i = ; i <= cnt; ++ i)
Net.Add(E[i].from, E[i].to, , );
for(int i = n + ; i <= n + m; ++ i)
Net.Add(i, n + m + , mv, );
return Net.MaxFlow(, n + m + ) == n;
} void Solve(){
int ans, l = ;
while(l <= r){
mid = l + (r - l) / ;
if(check(mid)){
ans = mid; r = mid - ;
}
else l = mid + ;
}
printf("%d\n", ans);
return;
}
int main(){ while(scanf("%d%d", &n, &m) && n && m){
cnt = ;r = ;
memset(bj, , sizeof bj);
Net.n = n + m + ;
for(int i = ; i <= n; ++ i){
getchar();gets(buf);
len = strlen(buf);
for(int j = ; j < len;){
if(buf[j] < '' || buf[j] > ''){
j ++; continue;
}
while(buf[j] <= '' && buf[j] >= ''){
x = x * + buf[j] - '';j ++;
}
++ cnt;
E[cnt] = (Edge){i, x + + n, , };
bj[E[cnt].to] ++;
r = max(bj[E[cnt].to], r);
x = ;
}
}
Solve();
}
return ;
}

POJ 2289

POJ 2289 Jamie's Contact Groups (二分+最大流)的更多相关文章

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

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

  2. 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 ...

  3. poj 2289 Jamie's Contact Groups【二分+最大流】【二分图多重匹配问题】

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

  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 & POJ3189 Steady Cow Assignment

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

  7. 图论--网络流--最大流 POJ 2289 Jamie's Contact Groups (二分+限流建图)

    Description Jamie is a very popular girl and has quite a lot of friends, so she always keeps a very ...

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

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

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

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

随机推荐

  1. OpenGL ES 2.0 内置变量

    1. 顶点着色器中的内置变量 输出变量 gl_Position(vec4):顶点数据位置gl_PointSize(float):计算一个点的大小 2.片元着色器中的内置变量 输入变量gl_FragCo ...

  2. nyoj 素数环

    算法:搜索 描述 有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环. 为了简便起见,我们规定每个素数环都从1开始.例如,下图就是6的一个素数环. 输 ...

  3. OpenSuse13.2硬盘安装

    直接参考文章:OpenSuse硬盘安装 补充: Win7引导Grub4dos时,本人尝试根据xp引导方式中使用boot.ini来引导,引导成功,不需要bcdedit命令,简化了引导步骤.

  4. 大转盘Demo

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  5. HTML5画布(圆形)

    案例1: <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8& ...

  6. C语言中关于字符串的一些常用函数

    使用以下时应当在头文件中加入string.h getch()为当你键入任何一个值时,返回但是并不显示,立马编译结束,返回的是asc码  getchar():当你键入回车之后才算是输入结束,并且可以用p ...

  7. libevent使用之安装(一)

    1.下载安装包,在官网http://www.monkey.org/~provos/libevent/下载 2.解压 运行命令: tar zxvf libevent-2.0.10-stable.tar. ...

  8. BasicExcel说明文档

    BasicExcel说明文档 BasicExcel原始链接:http://www.codeproject.com/Articles/13852/BasicExcel-A-Class-to-Read-a ...

  9. [HDU] 2094 产生冠军(拓扑排序+map)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2094 注意每组数据处理前,map要清空. #include<cstdio> #includ ...

  10. [POJ] 3468 A Simple Problem with Integers [线段树区间更新求和]

    A Simple Problem with Integers   Description You have N integers, A1, A2, ... , AN. You need to deal ...