POJ 2112 Optimal Milking(最大流-Dinic+Floyd+二分)
2015-08-08 09:24
549 查看
Description
有K台挤奶机(编号1~K),C头奶牛(编号K+1~K+C),都视为点,现在要让C头奶牛到挤奶机去挤奶,每台挤奶机只能处理M头奶牛,求使所走路程最远的奶牛的路程最短的方案
Input
第一行三个整数K,C,M分别表示挤奶机数量,奶牛数以及每台挤奶机能够处理的奶牛数,之后为以(K+C)*(K+C)矩阵表示奶牛与挤奶机之间的距离矩阵
Output
输出最小奶牛路程最大值
Sample Input
2 3 2
0 3 2 1 1
3 0 3 2 0
2 3 0 1 0
1 2 1 0 2
1 0 0 2 0
Sample Output
2
Solution
先用Floyd求所有点对之间最短路,二分最短长度,若奶牛与挤奶机之间的距离大于mid则不连边,否则连容量为1的边,源向奶牛流容量为1的边,挤奶机向汇点连容量为M的边,用Dinic算法求出最大流后看是否满流
注意:距离矩阵输入为0时则需将其改成INF
Code
有K台挤奶机(编号1~K),C头奶牛(编号K+1~K+C),都视为点,现在要让C头奶牛到挤奶机去挤奶,每台挤奶机只能处理M头奶牛,求使所走路程最远的奶牛的路程最短的方案
Input
第一行三个整数K,C,M分别表示挤奶机数量,奶牛数以及每台挤奶机能够处理的奶牛数,之后为以(K+C)*(K+C)矩阵表示奶牛与挤奶机之间的距离矩阵
Output
输出最小奶牛路程最大值
Sample Input
2 3 2
0 3 2 1 1
3 0 3 2 0
2 3 0 1 0
1 2 1 0 2
1 0 0 2 0
Sample Output
2
Solution
先用Floyd求所有点对之间最短路,二分最短长度,若奶牛与挤奶机之间的距离大于mid则不连边,否则连容量为1的边,源向奶牛流容量为1的边,挤奶机向汇点连容量为M的边,用Dinic算法求出最大流后看是否满流
注意:距离矩阵输入为0时则需将其改成INF
Code
#include<cstdio> #include<iostream> #include<cstring> #include<queue> using namespace std; #define maxn 333 #define maxm 100000 #define INF 1000000 int head[maxn],cur[maxn],d[maxn],st[maxm],s,e,no,n; struct point { int u,v,flow,next; point(){}; point(int x,int y,int z,int w):u(x),v(y),next(z),flow(w){}; }p[maxm]; void add(int x,int y,int z) { p[no]=point(x,y,head[x],z); head[x]=no++; p[no]=point(y,x,head[y],0); head[y]=no++; } void init() { memset(head,-1,sizeof(head)); no=0; } bool bfs() { int i,x,y; queue<int>q; memset(d,-1,sizeof(d)); d[s]=0; q.push(s); while(!q.empty()) { x=q.front(); q.pop(); for(i=head[x];i!=-1;i=p[i].next) { if(p[i].flow&& d[y = p[i].v]<0) { d[y]=d[x]+1; if(y==e) return true; q.push(y); } } } return false; } int dinic() { int i,loc,top,x=s,nowflow,maxflow=0; while(bfs()){ for(i=s;i<=e;i++) cur[i]=head[i]; top=0; while(true) { if(x==e) { nowflow=INF; for(i=0;i<top;i++) { if(nowflow>p[st[i]].flow) { nowflow=p[st[i]].flow; loc=i; } } for(i=0;i<top;i++) { p[st[i]].flow-=nowflow; p[st[i]^1].flow+=nowflow; } maxflow+=nowflow; top=loc; x=p[st[top]].u; } for(i=cur[x];i!=-1;i=p[i].next) if(p[i].flow&&d[p[i].v]==d[x]+1) break; cur[x]=i; if(i!=-1) { st[top++]=i; x=p[i].v; } else { if(!top) break; d[x]=-1; x=p[st[--top]].u; } } } return maxflow; } int K,C,M,dis[maxn][maxn]; bool check(int x) { init();//初始化 s=0;//源点为0 e=n+1;//汇点为n+1 for(int i=K+1;i<=K+C;i++)//源点与奶牛建容量为1的边 add(0,i,1); for(int i=1;i<=K;i++)//汇点与挤奶机建容量为M的边 add(i,n+1,M); for(int i=K+1;i<=K+C;i++) for(int j=1;j<=K;j++) if(dis[i][j]<=x)//奶牛与挤奶机之间距离不大于x则建一条容量为1的边 add(i,j,1); return dinic()==C;//判断是否满流 } int main() { while(~scanf("%d%d%d",&K,&C,&M)) { n=K+C; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&dis[i][j]); if(!dis[i][j])//如果距离输入为0则实际为INF dis[i][j]=INF; } for(int k=1;k<=n;k++)//Floyd for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); int left=0,right=10000; while(left<right)//二分最短长度 { int mid=(left+right)>>1; if(check(mid)) right=mid; else left=mid+1; } printf("%d\n",right); } return 0; }
相关文章推荐
- linux系统非ROOT用户80端口不能启动tomcat问题的变通办法——通过Iptables端口转发
- Linux下一个C基本的编程----写进Blog在那之前
- linux后台开发知识点
- Linux 环境变量的修复
- 阐述linux IPC(五岁以下儿童):system V共享内存
- Linux内存管理--内存回收(1)
- HDU 4362 Dragon Ball(维护最小值DP优化)
- 点滴记录一些shell命令
- 关于Connection must be valid and open.
- hdu1195(Open the Lock)
- 栈的push和pop判断
- shell 安装MYSQL
- 深度解读运维自动化
- 小米发布的运维监控工具:open falcon
- shell脚本_自动安装mysql
- CentOS7将普通用户添加到sudoers管理员组
- copy_from_user/copy_to_user函数中的buf参数释疑
- 为apache单独编译mod_rewrite.so
- EDK2 环境搭建 & Shell - Debug (cmd)
- Linux下如何查看系统启动时间和运行时间