POJ 2112 Optimal Milking(最大流)
题目链接:http://poj.org/problem?id=2112
Description
locations are named by ID numbers K+1..K+C.
Each milking point can "process" at most M (1 <= M <= 15) cows each day.
Write a program to find an assignment for each cow to some milking machine so that the distance the furthest-walking cow travels is minimized (and, of course, the milking machines are not overutilized). At least one legal assignment is possible for all input
data sets. Cows can traverse several paths on the way to their milking machine.
Input
* Lines 2.. ...: Each of these K+C lines of K+C space-separated integers describes the distances between pairs of various entities. The input forms a symmetric matrix. Line 2 tells the distances from milking machine 1 to each of the other entities; line 3 tells
the distances from machine 2 to each of the other entities, and so on. Distances of entities directly connected by a path are positive integers no larger than 200. Entities not directly connected by a path have a distance of 0. The distance from an entity
to itself (i.e., all numbers on the diagonal) is also given as 0. To keep the input lines of reasonable length, when K+C > 15, a row is broken into successive lines of 15 numbers and a potentially shorter line to finish up a row. Each new row begins on its
own line.
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
Source
题目描写叙述:(转)
k个机器,每一个机器最多服务m头牛。
c头牛,每一个牛须要1台机器来服务。
告诉你牛与机器每一个之间的直接距离。
问:让全部的牛都被服务的情况下,使走的最远的牛的距离最短,求这个距离。
解题报告:
二分枚举距离,实际距离满足当前枚举距离限制的能够增加这条边。
枚举的距离中符合条件的最小值就是答案。
建图过程:
一个超级原点,和每一个机器的容量都是m。
一个超级汇点,每头牛和汇点的容量都是1.
机器i与牛j之间的距离假设小于等于当前枚举值mid,连接i,j。容量1.
这样最大流的意义就是可以服务的牛最多是多少,假设最大流等于牛的总数c。表示当前枚举值mid符合条件,同一时候说明mid值还可能可以更小。更新二分右边界r = mid - 1.
假设小于牛的总数。说明mid偏小,更新二分左边界,l = mid + 1.
机器与牛之间的最短距离能够用floyd预处理出来。
代码例如以下:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 310;//点数的最大值
const int MAXM = 40010;//边数的最大值
const int INF = 0x3f3f3f3f;
struct Edge
{
int to,next,cap,flow;
} edge[MAXM]; //注意是MAXM
int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],cur[MAXN];
int k, c, m;
int s, e;//源点,汇点
int map[MAXN][MAXN];
int mid;//二分中间值;
int num;//矩阵的规格;
//加边,单向图三个參数,双向图四个參数
void addedge(int u,int v,int w,int rw = 0)
{
edge[tol].to = v;
edge[tol].cap = w;
edge[tol].flow = 0;
edge[tol].next = head[u];
head[u] = tol++;
edge[tol].to = u;
edge[tol].cap = rw;
edge[tol].flow = 0;
edge[tol].next = head[v];
head[v] = tol++;
}
int Q[MAXN]; void BFS(int start,int end)
{
memset(dep,-1,sizeof(dep));
memset(gap,0,sizeof(gap));
gap[0] = 1;
int front = 0, rear = 0;
dep[end] = 0;
Q[rear++] = end;
while(front != rear)
{
int u = Q[front++];
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(dep[v] != -1)continue;
Q[rear++] = v;
dep[v] = dep[u] + 1;
gap[dep[v]]++;
}
}
}
int S[MAXN];
//输入參数:起点、终点、点的总数
//点的编号没有影响,仅仅要输入点的总数
int sap(int start,int end,int N)
{
BFS(start,end);
memcpy(cur,head,sizeof(head));
int top = 0;
int u = start;
int ans = 0;
while(dep[start] < N)
{
if(u == end)
{
int Min = INF;
int inser;
for(int i = 0; i < top; i++)
if(Min > edge[S[i]].cap - edge[S[i]].flow)
{
Min = edge[S[i]].cap - edge[S[i]].flow;
inser = i;
}
for(int i = 0; i < top; i++)
{
edge[S[i]].flow += Min;
edge[S[i]^1].flow -= Min;
}
ans += Min;
top = inser;
u = edge[S[top]^1].to;
continue;
}
bool flag = false;
int v;
for(int i = cur[u]; i != -1; i = edge[i].next)
{
v = edge[i].to;
if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])
{
flag = true;
cur[u] = i;
break;
}
}
if(flag)
{
S[top++] = cur[u];
u = v;
continue;
}
int Min = N;
for(int i = head[u]; i != -1; i = edge[i].next)
if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
{
Min = dep[edge[i].to];
cur[u] = i;
}
gap[dep[u]]--;
if(!gap[dep[u]])return ans;
dep[u] = Min + 1;
gap[dep[u]]++;
if(u != start)u = edge[S[--top]^1].to;
}
return ans;
} void Foyld()//两个点的最短距离
{
for(int k = 1; k <= num; k++)
{
for(int i = 1; i <= num; i++)
{
for(int j = 1; j <= num; j++)
{
if(map[i][j] > map[i][k]+map[k][j])
{
map[i][j] = map[i][k]+map[k][j];
}
}
}
}
}
void init()
{
tol = 0;
memset(head,-1,sizeof(head));
for(int i = 1; i <= k; i++)//k个挤奶器
{
for(int j = k+1; j <= num; j++)//c头奶牛
{
if(map[i][j] <= mid)
{
//假设奶牛到挤奶器的最短距离<=mid,建权值为1的边
addedge(j,i,1);
}
}
}
for(int i = 1; i <= k; i++)
{
addedge(i,e,m);//每一个挤奶器最多能够挤k头牛
}
for(int i = k+1; i <= num; i++)
{
addedge(s,i,1);//建一条源点到奶牛的边。权值为1
}
}
int main()
{
while(~scanf("%d%d%d",&k,&c,&m))
{
num = k+c;
s = 0;//源点
e = num+1;//汇点
int nv = num+2; //结点总数
for(int i = 1; i <= num; i++)
{
for(int j = 1; j <= num; j++)
{
scanf("%d",&map[i][j]);
if(i!=j && !map[i][j])
{
map[i][j] = INF;
}
}
}
Foyld();
int l = 0, r = INF;
while(l <= r)
{
mid = (r+l)/2;
init();
if(sap(s, e, nv) == c)//最大流等于c
{
r = mid-1;
}
else
{
l = mid+1;
}
}
printf("%d\n",l);
}
return 0;
}
POJ 2112 Optimal Milking(最大流)的更多相关文章
- POJ 2112 Optimal Milking(最大流+二分)
题目链接 测试dinic模版,不知道这个模版到底对不对,那个题用这份dinic就是过不了.加上优化就WA,不加优化TLE. #include <cstdio> #include <s ...
- POJ 2112 Optimal Milking (二分 + floyd + 网络流)
POJ 2112 Optimal Milking 链接:http://poj.org/problem?id=2112 题意:农场主John 将他的K(1≤K≤30)个挤奶器运到牧场,在那里有C(1≤C ...
- POJ 2112 Optimal Milking (二分+最短路径+网络流)
POJ 2112 Optimal Milking (二分+最短路径+网络流) Optimal Milking Time Limit: 2000MS Memory Limit: 30000K To ...
- Poj 2112 Optimal Milking (多重匹配+传递闭包+二分)
题目链接: Poj 2112 Optimal Milking 题目描述: 有k个挤奶机,c头牛,每台挤奶机每天最多可以给m头奶牛挤奶.挤奶机编号从1到k,奶牛编号从k+1到k+c,给出(k+c)*(k ...
- POJ 2112 Optimal Milking (二分 + 最大流)
题目大意: 在一个农场里面,有k个挤奶机,编号分别是 1..k,有c头奶牛,编号分别是k+1 .. k+c,每个挤奶机一天最让可以挤m头奶牛的奶,奶牛和挤奶机之间用邻接矩阵给出距离.求让所有奶牛都挤到 ...
- POJ 2112—— Optimal Milking——————【多重匹配、二分枚举答案、floyd预处理】
Optimal Milking Time Limit:2000MS Memory Limit:30000KB 64bit IO Format:%I64d & %I64u Sub ...
- POJ 2112 Optimal Milking (Dinic + Floyd + 二分)
Optimal Milking Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 19456 Accepted: 6947 ...
- POJ 2112 Optimal Milking(二分+最大流)
http://poj.org/problem?id=2112 题意: 现在有K台挤奶器和C头奶牛,奶牛和挤奶器之间有距离,每台挤奶器每天最多为M头奶挤奶,现在要安排路程,使得C头奶牛所走的路程中的最大 ...
- POJ - 2112 Optimal Milking (dijkstra + 二分 + 最大流Dinic)
(点击此处查看原题) 题目分析 题意:在一个农场中有k台挤奶器和c只奶牛,每个挤奶器最多只能为m只奶牛挤奶,每个挤奶器和奶牛都视为一个点,将编号1~k记为挤奶器的位置,编号k+1~k+c记为奶牛的位置 ...
随机推荐
- 编写Shell脚本(未完待续)
Shell脚本命令的工作方式有两种:交互式批处理 交互式:用户每输入一条命令就立即执行 批处理:由用户事先编写好一个完整的Shell脚本,Shell会一次性执行脚本中诸多命令
- HTML5 book响应式翻页效果
翻页,HTML5源码下载,HTML5响应式翻页效果,鼠标移到右上角会看到翻页效果,需要鼠标拖动后翻页,支持ie9+,html5浏览器. 单页和双页. 自动播放和暂停. 点击左右翻页. 鼠标点击左右页面 ...
- Druid 常见问题
https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
- linux下使用free命令查看实际内存占用(可用内存)
转:http://blog.is36.com/linux_free_command_for_memory/ linux下在终端环境下可以使用free命令看到系统实际使用内存的情况,一般用free -m ...
- jq幻灯片2013-8-31
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- TCP常用网络和木马使用端口对照表,常用和不常用端口一览表
[开始-运行- CMD , 输入 netstat -an 然后回车就可以查看端口] 端口: 服务:Reserved 说明:通常用于分析操作系统.这一方法能够工作是因为在一些系统中“”是无效端口,当你试 ...
- OpenCV学习(4) Mat的基本操作(1)
图像在OpenCV中都是通过Mat类来存储的,Mat可以用来表示N维矩阵,当然用的最多的还是二维矩阵. Mat类有两部分组成:第一部分是头信息,这些信息主要用来描述矩阵,比如矩 ...
- XMPP键盘订制实现图文混排
在现阶段的通信服务中,各种标准都有,因此会出现无法实现相互连通,而XMPP(Extensible Message and presence Protocol)协议的出现,实现了整个及时通信服务协议的互 ...
- Android Logger日志系统
文件夹 文件夹 前言 执行时库层日志库liblog 源代码分析 CC日志写入接口 Java日志写入接口 logcat工具分析 基础数据结构 初始化过程 日志记录的读取过程 前言 该篇文章是我的读书和实 ...
- 在低带宽或不可靠的网络环境中安装 Visual Studio 2017
在低带宽或不可靠的网络环境中安装 Visual Studio 2017 2017-4-141 分钟阅读时长 作者 https://docs.microsoft.com/zh-cn/visualstu ...