poj 2391 Ombrophobic Bovines 最短路 二分 最大流 拆点
题目链接
题意
有\(n\)个牛棚,每个牛棚初始有\(a_i\)头牛,最后能容纳\(b_i\)头牛。有\(m\)条道路,边权为走这段路所需花费的时间。问最少需要多少时间能让所有的牛都有牛棚可待?
思路
二分
因为问题具有单调性,因此考虑二分时间,\(check\)是否满足条件。
满足条件指什么呢?
是指所有的牛都有牛棚可待。
是指所有的牛都顺利地从某一个牛棚移动到了另一个合法的牛棚(或者不移动),而这个移动是在限定的时间范围内的。
建图
首先拆点,将牛棚拆成 初始牛棚 与 终态牛棚。
在 源点 到 初始牛棚 之间连边,权值为初始时该牛棚内牛的个数。
在 终态牛棚 到 汇点 之间连边,权值为该牛棚最终可容纳的牛的个数。
在 初始牛棚 到 终态牛棚 之间连边:
\((u_i,v_j),(v_i,u_j)\):当且仅当移动的时间\(d(i,j)\)小于当前\(check\)的值时,才可以连这条边;
\((u_i,u_i)\):因为无需花费时间,所以永远可以连上。
这两类边的权值都是\(inf\),因为只要在限定的时间范围内,任意多的牛都可以从上面通过。
如果最大流对于源点而言是满流,则\(check\)成功
总括
综上所述,本题即最短路+二分+最大流
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#define inf1 0x3f3f3f3f3f3f3f3f
#define inf2 0x3f3f3f3f
#define maxn 1010
#define maxm 200010
using namespace std;
typedef long long LL;
LL a[maxn][maxn], mx, d;
struct Edge { int to, ne, c; }edge[maxm];
int dep[maxn], ne[maxn], tmp[maxn], n,m, tot, s,t,num, x[maxn], y[maxn];
void add(int u, int v, int c) {
edge[tot] = {v, ne[u], c};
ne[u] = tot++;
edge[tot] = {u, ne[v], 0};
ne[v] = tot++;
}
int bfs(int src) {
memset(dep, 0, sizeof dep);
dep[src] = 1;
queue<int> q;
while (!q.empty()) q.pop();
q.push(src);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = ne[u]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (edge[i].c > 0 && !dep[v]) dep[v] = dep[u] + 1, q.push(v);
}
}
return dep[t];
}
int dfs(int u, int flow) {
if (u == t) return flow;
int ret = 0;
for (int i = ne[u]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (edge[i].c > 0 && dep[v] == dep[u] + 1) {
int c = dfs(v, min(flow-ret, edge[i].c));
edge[i].c -= c;
edge[i^1].c += c;
ret += c;
if (ret == flow) break;
}
}
if (!flow) dep[u] = 0;
return ret;
}
void floyd() {
for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) a[i][j] = inf1;
for (int i = 1; i <= n; ++i) a[i][i] = 0;
while (m--) {
int u, v;
scanf("%d%d%lld", &u, &v, &d);
a[u][v] = a[v][u] = min(a[u][v], d);
}
for (int k = 1; k <= n; ++k) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (k==i||k==j) continue;
a[i][j] = a[j][i] = a[i][k]+a[k][j] < a[i][j] ? a[i][k]+a[k][j] : a[i][j];
}
}
}
mx = 0;
for (int i = 1; i <= n; ++i) for (int j = i+1; j <= n; ++j) if (a[i][j] != inf1) mx = max(mx, a[i][j]);
}
bool check(LL lim) {
tot = 0; memset(ne, -1, sizeof ne);
for (int i = 1; i <= n; ++i) {
add(s, i, x[i]); add(n+i, t, y[i]);
add(i, n+i, inf2);
}
int cnt = tot;
for (int i = s; i <= t; ++i) tmp[i] = ne[i];
for (int i = 1; i <= n; ++i) {
for (int j = i+1; j <= n; ++j) {
if (a[i][j] <= lim) add(i, n+j, inf2), add(j, n+i, inf2);
}
}
int ans=0, ret=0;
while (bfs(s)) {
while (ret = dfs(s, inf2)) ans += ret;
}
return ans == num;
}
int main() {
scanf("%d%d", &n, &m);
s = 0, t = n<<1|1, num = 0;
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &x[i], &y[i]);
num += x[i];
}
floyd();
LL l = 0, r = mx;
while (r > l) {
LL mid = l+r>>1;
if (check(mid)) r = mid;
else l = mid+1;
}
if (check(l)) printf("%lld\n", l);
else puts("-1");
return 0;
}
poj 2391 Ombrophobic Bovines 最短路 二分 最大流 拆点的更多相关文章
- POJ 2391 Ombrophobic Bovines(Floyd+二分+最大流)
题目链接 题意:农场有F(1 <= F <= 200)片草地用于放牛,这些草地有P(1 <= P <= 1500)连接,农场的草地上有一些避雨点,奶牛们可以在避雨点避雨,但是避 ...
- poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap
poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 ...
- poj 2391 Ombrophobic Bovines(最大流+floyd+二分)
Ombrophobic Bovines Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 14519Accepted: 3170 De ...
- POJ 2391 Ombrophobic Bovines (Floyd + Dinic +二分)
Ombrophobic Bovines Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11651 Accepted: 2 ...
- POJ 2391 Ombrophobic Bovines
Ombrophobic Bovines Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 18623 Accepted: 4 ...
- POJ 2391 Ombrophobic Bovines(二分+拆点+最大流)
http://poj.org/problem?id=2391 题意: 给定一个无向图,点i处有Ai头牛,点i处的牛棚能容纳Bi头牛,求一个最短时间T,使得在T时间内所有的牛都能进到某一牛棚里去. 思路 ...
- POJ 2391 Ombrophobic Bovines ( 经典最大流 && Floyd && 二分 && 拆点建图)
题意 : 给出一些牛棚,每个牛棚都原本都有一些牛但是每个牛棚可以容纳的牛都是有限的,现在给出一些路与路的花费和牛棚拥有的牛和可以容纳牛的数量,要求最短能在多少时间内使得每头牛都有安身的牛棚.( 这里注 ...
- POJ 2391 Ombrophobic Bovines ★(Floyd+二分+拆点+最大流)
[题意]有n块草地,一些奶牛在草地上吃草,草地间有m条路,一些草地上有避雨点,每个避雨点能容纳的奶牛是有限的,给出通过每条路的时间,问最少需要多少时间能让所有奶牛进入一个避雨点. 和POJ2112很类 ...
- POJ 2391 Ombrophobic Bovines (二分答案+floyd+最大流)
<题目链接> 题目大意: 给定一个有$n$个顶点和$m$条边的无向图,点$i$ 处有$A_i$头牛,点$i$ 处的牛棚能容纳$B_i$头牛,每条边有一个时间花费$t_i$(表示从一个端点走 ...
随机推荐
- Linux监控一之Nagios的安装与配置
一.Nagios简介 Nagios是一款开源的电脑系统和网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等.在系统或服务状态异常时发出邮件或短信报 ...
- Linux MySQL 8.0 忘记密码
不小忘了MySQL的密码,按照书上和网上的内容都没能修改成功,终于在借鉴了多篇文章成功之后找到原因,修改密码成功 修改 MySQL 密码 第一步:关闭 MySQL 进程 systemctl stop ...
- linux正则表达式基础部分
1.什么是正则表达式? 简单的说,正则表达式就是为处理大量的字符串而定义的一套规则和方法, 例如:假设“@”代表boy,“!”代表girl.echo“@!” === “boygirl” 通过定义的这些 ...
- 想成长为一名年薪50万+的实战型架构师?必掌握这7大实战技能经验--阿里mike
想成为一名架构师,但是架构师对应的技能,我应该掌握哪些啊?以及掌握的程度是什么样的?如何成为一名真正的实战性架构师? 我简要分为以下7点来谈谈,从技能的角度抛砖引玉,希望你对你架构师之路有一定的参考. ...
- Python9-MySQL-MySQL存储过程-视图-触发器-函数-day45
视图:某个查询语句设置别名,日后方便使用 CREATE VIEW v1 as SELECT * FROM student WHERE sid >10 -创建: create view 视图名称 ...
- Linux命令之---nl
命令简介 nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文件内容自动的加上行号!其默认的结果与 cat -n 有点不太一样, nl 可以将行号做比较多的显示设计,包括位数与是否自动补 ...
- 使用python实现简单爬虫
简单的爬虫架构 调度器 URL管理器 管理待抓取的URL集合和已抓取的URL,防止重复抓取,防止死循环 功能列表 1:判断新添加URL是否在容器中 2:向管理器添加新URL 3:判断容器是否为空 4: ...
- sql优化系列3(收集来源http://bbs.csdn.net/topics/250004467)
如何加快查询速度? 1.升级硬件 2.根据查询条件,建立索引,优化索引.优化访问方式,限制结果集的数据量. 3.扩大服务器的内存 4.增加服务器CPU个数 5.对于大的数据库不要设置数据库自动增长 ...
- Go语言之反射(二)
反射的值对象 反射不仅可以获取值的类型信息,还可以动态地获取或者设置变量的值.Go语言中使用reflect.Value获取和设置变量的值. 使用反射值对象包装任意值 Go语言中,使用reflect.V ...
- 【Distinct Subsequences】cpp
题目: Given a string S and a string T, count the number of distinct subsequences of T in S. A subseque ...