<题目链接>

题目大意:

给定一个有$n$个顶点和$m$条边的无向图,点$i$ 处有$A_i$头牛,点$i$ 处的牛棚能容纳$B_i$头牛,每条边有一个时间花费$t_i$(表示从一个端点走到另一个端点所需要的时间),求一个最短时间T使得在T时间内所有的牛都能进到某一牛棚里去。$(1 <= N <= 200, 1 <= M <= 1500,0 <= A_i <= 10^3, 0 <= B_i <= 10^3, 1 <= Dij <= 10^9)$。

解题分析:
很明显要二分答案,二分枚举最短的时间,然后用最大流去进行验证。将每个点$i$拆成两个点$i$和$i+n$,然后就是对于每次枚举的答案,进行重新建图,然后跑最大流,如果最大流等于所有牛的数量,则说明所有的牛都有牛棚能够停留,符合条件。建图的方法就是:超级源点向所有的点$i$连一条边,容量为i点初始牛的数量,所有点$i+n$向汇点连一条边,容量为该点牛的容量。因为点的数量很少,floyd预处理出任意两点之间的最短距离,然后对于每次枚举的时间T,最短距离小于等于T的边就加入网络,建好图之后,跑一遍最大流,进行判断。

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std; typedef long long ll;
const int N = ;
const ll INF = 1e18;
int n,m,st,ed;
int num[N],capa[N];
ll g[N][N],fullFlow; template<typename T>
inline void read(T&x){
x=;int f=;char c=getchar();
while(c<'' || c>''){ if(c=='-')f=-;c=getchar(); }
while(c>='' && c<=''){ x=x*+c-'';c=getchar(); }
x*=f;
}
struct Dinic
{
struct edge{ int from,to;ll cap,flow; };
vector<edge>es;
vector<int>G[N];
bool vis[N];
int g[N],iter[N];
void init(int n){
for(int i=; i<=n+; i++)G[i].clear();
es.clear();
}
void addedge(int from,int to,ll cap){
es.push_back((edge){from,to,cap,});
es.push_back((edge){to,from,,});
int x=es.size();
G[from].push_back(x-);
G[to].push_back(x-);
}
bool BFS(int s,int t){
memset(vis,,sizeof(vis));
queue <int> q;
vis[s]=;
g[s]=;
q.push(s);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=; i<G[u].size(); i++){
edge &e=es[G[u][i]];
if(!vis[e.to]&&e.cap>e.flow){
vis[e.to]=;
g[e.to]=g[u]+;
q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int u,int t,ll f){
if(u==t||f==)return f;
int numflow=,d;
for(int &i=iter[u]; i<G[u].size(); i++){
edge &e=es[G[u][i]];
if(g[u]+==g[e.to]&&(d=DFS(e.to,t,min(f,e.cap-e.flow)))>){
e.flow+=d;
es[G[u][i]^].flow-=d;
numflow+=d;
f-=d;
if(f==)break;
}
}
return numflow;
}
int Maxflow(int s,int t){
int flow=;
while(BFS(s,t)){
memset(iter,,sizeof(iter));
int d=;
while(d=DFS(s,t,INF))flow+=d;
}
return flow;
}
}dinic; bool check(ll T){ //最长的时间限制
dinic.init(N);
for(int i=;i<=n;i++){
dinic.addedge(st,i,num[i]); //源点向每个点连一条边,容量为这个点的牛的数量
dinic.addedge(i+n,ed,capa[i]); //每个点拆点之后的点向汇点连一条边,容量为这个点能够容纳牛的数量
}
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(g[i][j]<=T) //将符合条件的边加上
dinic.addedge(i,j+n,INF);
return dinic.Maxflow(st,ed) == fullFlow; //判断是否满流,即是否所有的牛都有牛棚住
}
inline void Floyd(){ //floyd求出任意两点之间的最短距离
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(g[i][j]>g[i][k]+g[k][j])
g[i][j]=g[i][k]+g[k][j];
}
inline void Init(){
fullFlow = ;
st=,ed=*n+;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
g[i][j]=(i==j)?:INF; //初始化任意两点之间的距离
for(int i=;i<=n;i++){
read(num[i]);read(capa[i]);
fullFlow +=num[i]; //记录所有牛的数量
}
for(int i=;i<=m;i++){
int u,v;ll w;
read(u);read(v);read(w);
g[u][v]=g[v][u]=min(g[u][v],w);
}
Floyd();
}
int main(){
while(~scanf("%d%d",&n,&m)){
Init();
ll l=,r=;//二分的上下界
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(g[i][j]<INF)
r=max(r,g[i][j]); //找到时间的上界
ll ans=-; //二分答案
while(l<=r){
ll mid=(l+r)>>;
if(check(mid))ans=mid,r=mid-;
else l=mid+;
}
printf("%lld\n",ans);
}
}

POJ 2391 Ombrophobic Bovines (二分答案+floyd+最大流)的更多相关文章

  1. poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap

    poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 ...

  2. POJ 2391 Ombrophobic Bovines ★(Floyd+二分+拆点+最大流)

    [题意]有n块草地,一些奶牛在草地上吃草,草地间有m条路,一些草地上有避雨点,每个避雨点能容纳的奶牛是有限的,给出通过每条路的时间,问最少需要多少时间能让所有奶牛进入一个避雨点. 和POJ2112很类 ...

  3. POJ 2391 Ombrophobic Bovines (Floyd + Dinic +二分)

    Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11651   Accepted: 2 ...

  4. poj 2391 Ombrophobic Bovines(最大流+floyd+二分)

    Ombrophobic Bovines Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 14519Accepted: 3170 De ...

  5. POJ 2391 Ombrophobic Bovines(Floyd+二分+最大流)

    题目链接 题意:农场有F(1 <= F <= 200)片草地用于放牛,这些草地有P(1 <= P <= 1500)连接,农场的草地上有一些避雨点,奶牛们可以在避雨点避雨,但是避 ...

  6. POJ 2391 Ombrophobic Bovines ( 经典最大流 && Floyd && 二分 && 拆点建图)

    题意 : 给出一些牛棚,每个牛棚都原本都有一些牛但是每个牛棚可以容纳的牛都是有限的,现在给出一些路与路的花费和牛棚拥有的牛和可以容纳牛的数量,要求最短能在多少时间内使得每头牛都有安身的牛棚.( 这里注 ...

  7. POJ 2391 Ombrophobic Bovines

    Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18623   Accepted: 4 ...

  8. poj 2391 Ombrophobic Bovines【最大流】

    我%--&(¥--,调了一下午,最后发现P赋值1e5能过,赋值1e6就会TLE致死.改了一下午加一晚上然而这是为什么??? 一种常见的建图套路,首先二分答案,注意上界要取大一点,1e9是不行的 ...

  9. POJ 2391 Ombrophobic Bovines(二分+拆点+最大流)

    http://poj.org/problem?id=2391 题意: 给定一个无向图,点i处有Ai头牛,点i处的牛棚能容纳Bi头牛,求一个最短时间T,使得在T时间内所有的牛都能进到某一牛棚里去. 思路 ...

随机推荐

  1. mongoDB 文档操作_改

    mongoDB 更改操作 格式对比 MySQL update table set .... where .... db.collection.updateOne(query,update,upsert ...

  2. l2tp pptp相关的一些记录

    添加用户名和密码 echo "user l2tpd password *">>/etc/ppp/chap-secrets /etc/ipsec.conf dpddela ...

  3. java 11 标准Java异步HTTP客户端

    这是 Java 9 开始引入的一个处理 HTTP 请求的的 HTTP Client API,该 API 支持同步和异步,而在 Java 11 中已经为正式可用状态,你可以在 java.net 包中找到 ...

  4. vue学习笔记(三)- vue2.x引入Element-ui

    webpack+vue2.x+element-ui 作者:狐狸家的鱼 本文链接:vue2.x引入Element-ui GitHub:sueRimn 1.新建项目 vue init webpack vu ...

  5. Linux下查看Nginx安装目录、版本号信息及当前运行的配置文件

    Linux环境下,怎么确定Nginx的安装路径 输入命令行: ps -ef | grep nginx 摁回车,将出现如下图片: master process 后面的就是的 /data/software ...

  6. Mock5 moco框架中post请求如何加入cookies

    接着Mock4中的json文件,再往里面添加一个post 请求. 前面写法不变,后面的请求数据用的是json关键字,返回的response也是json的格式 [ { "description ...

  7. Stanford Local 2016 E "Election of Evil"(搜索(正解)或并查集(划掉))

    传送门 题意: 给出集合U,V,集合U有n个元素,集合V有m个元素: 有 m 个操作,mi : s1 s2 有一条s1指向s2的边(s1,s2可能属于第三个集合,暂且称之为K集合): 指向边具有传递性 ...

  8. Java斗地主案例、异常和自定义异常整理

    模拟斗地主洗牌发牌 1.1 案例介绍 按照斗地主的规则,完成洗牌发牌的动作. 具体规则: 1. 组装54张扑克牌 2. 将54张牌顺序打乱 3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张 ...

  9. OS + CentOS / http_proxy / https_proxy / dalishangwang / repo

    s OS + Linux RedHat / redhat7 / redhat 7 / redhat 6 / redhat 5 https://lindows.iteye.com/blog/456637 ...

  10. 分布式监控系统开发【day38】:报警模块解析(六)

    一.负责把达到报警条件的trigger进行分析 ,并根据 action 表中的配置来进行报警 1.目录结构 2.功能如下 1.找到trigger的关联动作, 2.收到的数据传给trigger_msg就 ...