题目大意:你的手机通讯录里有n个联系人,m个分组,其中,有的联系人在多个分组里。你的任务是在一些分组里删除一些联系人,使得每个联系人只在一个分组里并且使人数最多的那个分组人数最少。找出人数最多的那个分组中的人数。

题目分析:要求的是最小的最大值,二分枚举这个最小的最大人数x。增加源点s和汇点t,从s向每一个联系人连一条弧,容量为1,表示一个联系人只能在一个分组中;然后对于每个联系人向他所在的分组连一条弧,容量为1,表示在这个分组里最多保存一次该联系人;然后从每个分组向汇点连一条弧,容量为x,表示这个分组不能保存超过x个联系人。求最大流,如果源点s出发的每条边都满载,说明x可行。

代码如下:

# include<iostream>
# include<cstdio>
# include<cmath>
# include<string>
# include<vector>
# include<list>
# include<set>
# include<map>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std; # define LL long long
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a))
# define CLL(a,b,n) fill(a,a+n,b) const double inf=1e30;
const int INF=1<<30;
const int N=1505; struct Edge
{
int fr,to,cap,fw;
Edge(int _fr,int _to,int _cap,int _fw):fr(_fr),to(_to),cap(_cap),fw(_fw){}
};
vector<Edge>edges,tedges;
vector<int>G[N];
int cur[N],vis[N],d[N],mark[505]; void init(int n)
{
edges.clear();
REP(i,0,n) G[i].clear();
} void addEdge(int u,int v,int cap)
{
edges.push_back(Edge(u,v,cap,0));
edges.push_back(Edge(v,u,0,0));
int m=edges.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
} bool BFS(int s,int t)
{
CL(vis,0);
vis[s]=1;
d[s]=0;
queue<int>q;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
REP(i,0,G[u].size()){
Edge &e=edges[G[u][i]];
if(!vis[e.to]&&e.cap>e.fw){
d[e.to]=d[u]+1;
vis[e.to]=1;
q.push(e.to);
}
}
}
return vis[t];
} int DFS(int u,int t,int a)
{
if(u==t||a==0) return a;
int flow=0,f;
for(int &i=cur[u];i<G[u].size();++i){
Edge &e=edges[G[u][i]];
if(d[e.to]==d[u]+1&&(f=DFS(e.to,t,min(a,e.cap-e.fw)))>0){
e.fw+=f;
edges[G[u][i]^1].fw-=f;
flow+=f;
a-=f;
if(a==0) break;
}
}
return flow;
} int Dinic(int s,int t)
{
int flow=0;
while(BFS(s,t)){
CL(cur,0);
flow+=DFS(s,t,INF);
}
return flow;
} bool read(int &x)
{
x=0;
char c;
while(c=getchar()){
if(c==' ') return true;
else if(c=='\n') return false;
else x=x*10+c-'0';
}
} bool judge()
{
REP(i,0,G[0].size())
if(edges[G[0][i]].cap>0&&edges[G[0][i]].cap!=edges[G[0][i]].fw) return false;
return true;
} int main()
{
int n,m;
char name[20];
while(scanf("%d%d",&n,&m)&&(n+m))
{
init(n+m+2);
CL(mark,0);
REP(i,1,n+1){
cin>>name;
addEdge(0,m+i,1);
int a;
getchar();
while(read(a)){
++mark[a];
addEdge(m+i,a+1,1);
}
addEdge(m+i,a+1,1);
++mark[a];
} int cnt=edges.size();
tedges.clear();
REP(i,0,cnt) tedges.push_back(edges[i]); int l=0,r=0;
REP(i,0,m) r=max(r,mark[i]);
while(l<r){
int mid=l+(r-l)/2;
init(n+m+2);
REP(i,0,cnt) addEdge(tedges[i].fr,tedges[i].to,tedges[i].cap);
REP(i,0,m) if(mark[i])
addEdge(i+1,n+m+1,min(mid,mark[i]));
Dinic(0,n+m+1);
if(judge()) r=mid;
else l=mid+1;
}
printf("%d\n",l);
}
return 0;
}

  

UVALive-3268 Jamie's Contact Groups (最大流,网络流建模)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  10. 图论--网络流--最大流 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 ...

随机推荐

  1. Centos忘记root密码重置

    entos6.5忘记root密码重置 一,启动服务器按e键 二,按e键选择第二项 三,在ro root前输入single回车保存 四,回到前面一个界面按b键启动 不用密码即可启动输入passwd修改r ...

  2. opencv学习笔记——minMaxIdx函数的含义及用法

    opencv中有时需要对Mat数据需要对其中的数据求取最大值和最小值.opencv提供了直接的函数 CV_EXPORTS_W void minMaxLoc(InputArray src, CV_OUT ...

  3. SQL的子查询操作

    对于表中的每一个记录,我们有时候需要提取特殊的或者你需要的记录,要提前做一个表的筛选,之后再对你选出的记录做一个修改,此时你必须使用SQL的子查询操作.如:修改id=5的记录的strContent字段 ...

  4. State of the official Elasticsearch Java clients

    Elasticsearch Java Clients | Elastic https://www.elastic.co/blog/state-of-the-official-elasticsearch ...

  5. C# WinForm实现任务栏程序图标闪烁

    相信大家在用QQ的时候都会知道,你打开了QQ聊天窗口,如果窗口不是当前激活的窗口的话,收到QQ消息时,任务栏(不是托盘图标)上的图标会闪一下变成黄色(Win7默认主题下),用以通知用户有消息进来了,之 ...

  6. 前端迭代取出 后台map返回的数据

    <body> <div th:each="map : ${response}"> <span th:text="${map.key}&quo ...

  7. hdu1286(找新朋友)&&POJ2407Relatives(欧拉函数模版题)

    http://acm.hdu.edu.cn/showproblem.php?pid=1286 没什么好说的,模板题,主要是弄懂欧拉函数的思想. #include <iostream> #i ...

  8. POJ2891:Strange Way to Express Integers(解一元线性同余方程组)

    写一下自己的理解,下面附上转载的:若a==b(modk);//这里的==指的是同余,我用=表示相等(a%k=b)a-b=kt(t为整数)以前理解的错误思想:以前认为上面的形式+(a-tb=k)也是成立 ...

  9. (1)R介绍

    1. R初窥 从CRAN(The Comprehensive R Archive Network)cran.r-project.org—mirrors.html中选择一个镜像,然后下载合适的安装包(R ...

  10. Linux学习笔记之Linux最小化安装启动后如何配置

    在VM虚拟机中安装CentOS 7 时 有时候顾虑到电脑硬件性能,我们需要最小化安装,而最小化安装后与centos6的版本是有一些差异的,接下来我们就对刚安装好的最小化centos7做一些操作,来世我 ...