题意:

  一些人,和他们可能加入的组号。问每个组,最小的最大人数是多少

分析:

  二分的是最大流的容量。设置一个超级源点,连向所有的人,容量为1。设置一个超级汇点,使所有的组连向超级汇点,二分的就是这里的容量(0~n)。然后根据题目给出的人和组的关系连接人和组,容量为1。二分时,若当前状态求出的最大流等于人数,则下界等于mid,若不等于,则上界等于mid。二分出的容量,就是组中的最小的最大人数。

输入:

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

输出:

2

2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <sstream>
using namespace std;
const int maxn=3010;
const int inf=1e9;
int n,m;
structEdge
{
int u,v;
int flow,cap;
Edge(int uu,int cc,int fl,int ca):u(uu),v(cc),flow(fl),cap(ca)
{ }
};
vector<Edge>edge;
structISAP
{
vector<int>G[maxn];
vector<Edge>edge;
int s,t;
int d[maxn];
int cur[maxn];
int p[maxn];
int num[maxn];
int flow;
void init()
{
for(int i=0;i<=n+m+1;i++)
G[i].clear();
s=0;
t=n+m+1;
}
bool bfs()
{
memset(d,-1,sizeof(d));
queue<int>q;
q.push(t);
d[t]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<G[u].size();i++)
{
Edge& e=edge[G[u][i]];
if(e.cap==0&&d[e.v]==-1)
{
d[e.v]=d[u]+1;
q.push(e.v);
}
}
}
return d[s]!=-1;
}
int Augment()
{
int x=t,a=inf;
while(x!=s)
{
Edge& e=edge[p[x]];
a=min(a,e.cap-e.flow);
x=edge[p[x]].u;
}
x=t;
while(x!=s)
{
edge[p[x]].flow+=a;
edge[p[x]^1].flow-=a;
x=edge[p[x]].u;
}
return a;
}
int maxflow(int s,int t)
{
this->s=s;
this->t=t;
flow=0;
bfs();
for(int i=0;i<=n+m+1;i++)
num[d[i]]++;
int x=s;
memset(cur,0,sizeof(cur));
while(d[s]<n+m+2)
{
if(x==t)
{
flow+=Augment();
x=s;
}
bool ok=false;
for(int i=cur[x];i<G[x].size();i++)
{
Edge& e=edge[G[x][i]];
if(e.cap>e.flow&&d[x]==d[e.v]+1)
{
ok=true;
p[e.v]=G[x][i];
cur[x]=i;
x=e.v;
break;
}
}
if(!ok)
{
int k=n+m+1;
for(int i=0;i<G[x].size();i++)
{
Edge& e=edge[G[x][i]];
if(e.cap>e.flow)
k=min(k,d[e.v]);
}
if(--num[d[x]]==0)
break;
num[d[x]=k+1]++;
cur[x]=0;
if(x!=s)
x=edge[p[x]].u;
}
}
return flow;
}
}solver;
char buffer[11000];
void add(int s,int t,int cap)
{
edge.push_back(Edge(s,t,0,cap));
edge.push_back(Edge(t,s,0,0));
int x=edge.size();
solver.G[s].push_back(x-2);
solver.G[t].push_back(x-1);
}
void input()
{
solver.init();
int x;
edge.clear();
char ch[100];
for (int i = 1 ; i <= n ; ++i)
{
add(0,i,1);
scanf("%*s");
gets(buffer);
char * p = strtok(buffer, " ");
while (p) {
sscanf(p,"%d",&x);
add(i,x+1+n,1);
p = strtok(NULL," ");
}
}
int sz=edge.size();
for(int i=n+1;i<=n+m;i++)
{
sz+=2;
solver.G[i].push_back(sz-2);
solver.G[n+m+1].push_back(sz-1);
}
}
void build(int up)
{
solver.edge=edge;
for(int i=n+1;i<=n+m;i++)
{
solver.edge.push_back(Edge(i,n+m+1,0,up));
solver.edge.push_back(Edge(n+m+1,i,0,0));
}
}
void solve()
{
int left=1,right=n;
int mid=(left+right)>>1;
int ans=n;
while(left<=right)
{
build(mid);
if (solver.maxflow(0,n+m+1)==n)
{
right = mid-1;
ans = min(ans,mid);
}
else
{
left = mid+1;
}
mid = (left+right)>>1;
}
printf("%d\n",ans);
}
int main()
{
while(scanf("%d%d",&n,&m)==2,n+m)
{
input();
solve();
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <sstream>
using namespace std;
const int maxn=3010;
const int inf=1e9;
int n,m;
structEdge
{
int u,v;
int flow,cap;
Edge(int uu,int cc,int fl,int ca):u(uu),v(cc),flow(fl),cap(ca)
{ }
};
vector<Edge>edge;
structISAP
{
vector<int>G[maxn];
vector<Edge>edge;
int s,t;
int d[maxn];
int cur[maxn];
int p[maxn];
int num[maxn];
int flow;
void init()
{
for(int i=0;i<=n+m+1;i++)
G[i].clear();
s=0;
t=n+m+1;
}
bool bfs()
{
memset(d,-1,sizeof(d));
queue<int>q;
q.push(t);
d[t]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<G[u].size();i++)
{
Edge& e=edge[G[u][i]];
if(e.cap==0&&d[e.v]==-1)
{
d[e.v]=d[u]+1;
q.push(e.v);
}
}
}
return d[s]!=-1;
}
int Augment()
{
int x=t,a=inf;
while(x!=s)
{
Edge& e=edge[p[x]];
a=min(a,e.cap-e.flow);
x=edge[p[x]].u;
}
x=t;
while(x!=s)
{
edge[p[x]].flow+=a;
edge[p[x]^1].flow-=a;
x=edge[p[x]].u;
}
return a;
}
int maxflow(int s,int t)
{
this->s=s;
this->t=t;
flow=0;
bfs();
for(int i=0;i<=n+m+1;i++)
num[d[i]]++;
int x=s;
memset(cur,0,sizeof(cur));
while(d[s]<n+m+2)
{
if(x==t)
{
flow+=Augment();
x=s;
}
bool ok=false;
for(int i=cur[x];i<G[x].size();i++)
{
Edge& e=edge[G[x][i]];
if(e.cap>e.flow&&d[x]==d[e.v]+1)
{
ok=true;
p[e.v]=G[x][i];
cur[x]=i;
x=e.v;
break;
}
}
if(!ok)
{
int k=n+m+1;
for(int i=0;i<G[x].size();i++)
{
Edge& e=edge[G[x][i]];
if(e.cap>e.flow)
k=min(k,d[e.v]);
}
if(--num[d[x]]==0)
break;
num[d[x]=k+1]++;
cur[x]=0;
if(x!=s)
x=edge[p[x]].u;
}
}
return flow;
}
}solver;
char buffer[11000];
void add(int s,int t,int cap)
{
edge.push_back(Edge(s,t,0,cap));
edge.push_back(Edge(t,s,0,0));
int x=edge.size();
solver.G[s].push_back(x-2);
solver.G[t].push_back(x-1);
}
void input()
{
solver.init();
int x;
edge.clear();
char ch[100];
for (int i = 1 ; i <= n ; ++i)
{
add(0,i,1);
scanf("%*s");
gets(buffer);
char * p = strtok(buffer, " ");
while (p) {
sscanf(p,"%d",&x);
add(i,x+1+n,1);
p = strtok(NULL," ");
}
}
int sz=edge.size();
for(int i=n+1;i<=n+m;i++)
{
sz+=2;
solver.G[i].push_back(sz-2);
solver.G[n+m+1].push_back(sz-1);
}
}
void build(int up)
{
solver.edge=edge;
for(int i=n+1;i<=n+m;i++)
{
solver.edge.push_back(Edge(i,n+m+1,0,up));
solver.edge.push_back(Edge(n+m+1,i,0,0));
}
}
void solve()
{
int left=1,right=n;
int mid=(left+right)>>1;
int ans=n;
while(left<=right)
{
build(mid);
if (solver.maxflow(0,n+m+1)==n)
{
right = mid-1;
ans = min(ans,mid);
}
else
{
left = mid+1;
}
mid = (left+right)>>1;
}
printf("%d\n",ans);
}
int main()
{
while(scanf("%d%d",&n,&m)==2,n+m)
{
input();
solve();
}
}

UVA 1345 Jamie's Contact Groups的更多相关文章

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

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

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

  3. Jamie's Contact Groups POJ - 2289(多重匹配 最大值最小化 最大流)

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

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

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

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

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

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

    Jamie's Contact Groups Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/ ...

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

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

  8. POJ2289 Jamie's Contact Groups —— 二分图多重匹配/最大流 + 二分

    题目链接:https://vjudge.net/problem/POJ-2289 Jamie's Contact Groups Time Limit: 7000MS   Memory Limit: 6 ...

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

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

随机推荐

  1. Github错误:Failed to publish this branch

    转自:http://jingpin.jikexueyuan.com/article/34632.html 今天弄github的时候,客户端一直出现error to publish this branc ...

  2. 9、Khala实现0.01版QQ

    这次来个有界面的. 登录界面: 主界面: 1.服务端开发: 只需创建一个类ChatType(./examples/HelloKhala/src/ChatType.cpp),在该类型中,核心为创建的两个 ...

  3. 驱动编程思想之初体验 --------------- 嵌入式linux驱动开发之点亮LED

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

  4. Python学习笔记5(字符串与正则表达式)

    1.字符串 1.1字符串的格式化 #格式化语法 "%s" % str1 "%s %s" % (str1,str2) #格式化字符串 str1 = "v ...

  5. 解决: AGPBI: {"kind":"error","text":"indicate that it is *not* an inner class.","sources":[{}]}

    关于Gradle Console输出类似这样错误信息: AGPBI: {"kind":"error","text":"indica ...

  6. [C++程序设计]函数的递归调用

    在调用一个函数的过程中又出现直接或间接地调用 该函数本身,称为函数的递归(recursive)调用. 包含递归调用的函数称为递归函数. 在实现递归时,在时间和空间上的开销比较大 求n! #includ ...

  7. zabbix之2安装编译/基本功能实现

    1.安装方式: rpm或者编译都可,rpm可以直接用yum安装. rpm安装的话,根据文件名进行选择即可. 编译的话,不同参数对应不同的组件. 编译安装zabbix:同时安装server和agent, ...

  8. Monkey学习笔记<四>:Monkey服务器命令

    #使用如下命令将本地pc和手机连接起来 adb shell monkey --port 1080 adb forward tcp 1080:tcp 1080 telnet localhost 1080 ...

  9. Linux下MySQL 5.6的修改字符集编码为UTF8(彻底解决中文乱码问题)

    一.登录MySQL查看用SHOW VARIABLES LIKE ‘character%’;下字符集,显示如下:+--------------------------+----------------- ...

  10. BZOJ 1458 士兵占领

    http://www.lydsy.com/JudgeOnline/problem.php?id=1458 题意:n x m的棋盘,k个位置不能放,每行和每列都有要求至少的士兵,求能否有最少的满足条件的 ...