UVA3268 二分+最大流,嘿嘿嘿
来源:互联网 发布:李涛疯狂淘宝靠谱吗 编辑:程序博客网 时间:2024/04/30 14:48
题目
题意:你的手机通讯录里有n个联系人,m个分组,其中,有的联系人在多个分组里。你的任务是重新规划通讯录,使得每个联系人只在一个分组里并且使人数最多的那个分组人数最少。找出人数最多的那个分组中的人数
分析:看到要求最大值的最小值(人数最多的那组的人数最少),很容易想到二分答案。
然后check就懵逼,自己一开始想什么贪心乱搞,
然后看一下白书,又看看题解,卧槽最大流。
原谅我之前不会网络流,先看紫书,看到最后说效率不够
再看蓝书,DFS+BFS版本的Dinic算法,,,
分析的分析:二分人数最多的组的人数,以此为最大流量跑最大流,
增加节点:0=s,1~n为n个人,n+1~n+m为m个分组,n+m+1为t
从s向每一个联系人连一条弧,容量为1,表示一个联系人只能在一个分组中;然后对于每个联系人向他所在的分组连一条弧,容量为1,表示在这个分组里最多保存一次该联系人;然后从每个分组向汇点连一条弧,容量为x,表示这个分组不能保存超过x个联系人
如果最后每个点的流量都是1,表示每个人都走过了,return 1
废话一大堆,主要记录一下,最大流的模板
#include<queue>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>using namespace std;const int N=2333;struct Edge{ int from,to,cap,flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}};int s,t,n,m,top;vector<Edge>edges;//0=s,1~n人,n+1~n+m组,n+m+1=tvector<int>G[N];//邻接表vector<int>group[N];//记录每个人属于集合bool vis[N];//use when bfsint d[N],cur[N];//dist,now edgevoid AddEdge(int from,int to,int cap){ edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from, 0 ,0)); top=edges.size(); G[from].push_back(top-2); G[ to ].push_back(top-1);}bool BFS(){ memset(vis,0,sizeof(vis)); queue<int>Q; Q.push(s);d[s]=0;vis[s]=1; 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)continue; vis[e.to]=1; 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[x]+1!=d[e.to])continue; if ((f=DFS(e.to,min(a,e.cap-e.flow)))<=0)continue; e.flow+=f; edges[G[x][i]^1].flow-=f; flow+=f; a-=f; if (a==0)break; } return flow;}int Maxflow(int s,int t,int x){ int flow=0; while(BFS()){ memset(cur,0,sizeof(cur)); flow+=DFS(s,x); } return flow;}bool check(int x){ edges.clear(); //init for (int i=0;i<=n+m+1;i++)G[i].clear(); for (int i=n+1;i<=n+m;i++)AddEdge(i,t,x); for (int i=1;i<=n;i++){ AddEdge(s,i,1); for (int j=0;j<group[i].size();j++){ AddEdge(i,group[i][j],1); } } int flow=Maxflow(s,t,x); //run for (int i=0;i<G[s].size();i++){ if (edges[G[s][i]].flow!=1)return 0; } return 1;}int main(){ //freopen("fuck.in","r",stdin); int k; char ch; for (;scanf("%d%d",&n,&m)==2&&(n+m);){ s=0;t=m+n+1; //read for (int i=1;i<=n;i++){ string st;cin>>st; group[i].clear(); while (~scanf("%c",&ch)&&ch!='\n'){ scanf("%d",&k); group[i].push_back(n+k+1); } } int L=0,R=n; //erfen while (L<R){ if (L==R)break; int mid=(L+R)>>1; bool ok=check(mid); if (ok) R=mid; else L=mid+1; } printf("%d\n",L); }}
0 0
- UVA3268 二分+最大流,嘿嘿嘿
- 嘿嘿嘿
- 嘿嘿嘿
- poj2391Floyd+二分+最大流
- poj2112二分+最大流
- hdu4560 最大流+二分
- poj2112 二分+最大流
- POJ3228二分最大流
- nefu500(二分+最大流)
- 最大流 二分图
- hdu5855二分+最大流
- poj2112 二分最大流
- bzoj1433_最大流|二分图最大匹配
- HUST1024二分答案+最大流
- poj 2112(二分+最大流)
- POJ 2289 二分最大流
- poj 2455 最大流+二分
- POJ 2455 二分+最大流
- 【转】Activity启动模式图文详解:standard, singleTop, singleTask 以及 singleInstance
- 线程池ThreadPoolExecutor参数设置
- iOS项目的完整重命名方法图文教程
- 利用Spark Streaming来实现实时的数据管道服务
- Peeking into Linux kernel-land using /proc filesystem for quick’n’dirty troubleshooting
- UVA3268 二分+最大流,嘿嘿嘿
- getline()之前存在cin时的使用
- 波动序列
- 【bug】使用pixi做虚拟摇杆时候发现的bug-不同的touch事件最后都可以出发touchend,即使没有touchstart先
- 【MFC-10】VS2010/MFC基于对话框程序的登录窗口实现
- v8的编译
- nginx + php-fpm fastcgi防止跨站、跨目录的安全设置
- js中使用jstl中得到的值
- Android编码规范