这道题非常好,如果没有真正弄懂费用流算法的人,只会套模版的人是肯定做不出来的。

我们其实这样考虑,费用流真正的思想是吧费用作为长度,然后跑最短路,同时保证路上的流量不为0,也就是增广;

跑到终点后,回溯把路上的流量进行修改。一直这样下去直到无法增广。

这道题也是一样,我们把路径长度看成费用,路径限制看成流量限制。

每次增广到终点后,得到的dis[t]代表源点到汇点的路径长度,incf[t]代表的是这条路上的流量限制。

每一次增广成功,我们都会获得一个和之前不同的路径。

这样我们就能够得到所有s-t路径长度,以及长度对应的流量限制。并且他们所有路径都是满足在流量限制条件下的。

然后其实就很简单了,我们知道我们需要运输的人数,同时知道每一条路径对应的路径的路径运输能力和路径长度,那么我们对答案进行二分,也就是对总共用的时间进行二分。

对于所有路径长度是>=总共运输时间的(每次速度为1),也就是说对于当前的时间内,这条路是可以运载一些人到终点的,那么这条路运输的人数其实就是  e[i].flow*(t-e[i].dist+1)

也就是当前道路的流量*(所用的时间-从起点到终点的时间+1),因为当前道路的在前dist-1的时间内,人还在路上,没有抵达,在dist时间以后,人会源源不断的来到。

注意k可能是0,需要先特判k=0,再特判最大流量=0。不然会错。。。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#define LL long long
using namespace std;
const int maxx = 2e5+;
const LL INF = 1e18;
int ver[maxx],head[maxx],Next[maxx];
LL incf[maxx];
LL cost[maxx],edge[maxx];
int v[maxx],pre[maxx];
LL d[maxx];
int tot,cnt,n,m,s,t;
LL ans,k,maxflow;
struct node
{
LL flow;
LL w;
} a[maxx];
void add(int x,int y,LL z,LL c)
{
ver[++tot]=y;
edge[tot]=z;
cost[tot]=c;
Next[tot]=head[x];
head[x]=tot;
ver[++tot]=x;
edge[tot]=;
cost[tot]=-c;
Next[tot]=head[y];
head[y]=tot;
}
bool spfa()
{
queue<int>q;
while(q.size())q.pop();
for (int i=; i<=n+; i++)
{
d[i]=INF;
v[i]=;
}
q.push(s);
d[s]=;
v[s]=;
incf[s]=INF;
while(q.size())
{
int x=q.front();
v[x]=;
q.pop();
for (int i=head[x]; i; i=Next[i])
{
if (!edge[i])
continue;
int y=ver[i];
//cout<<x<<" "<<y<<" "<<edge[i]<<endl;
if(d[y]>d[x]+cost[i])
{
d[y]=d[x]+cost[i];
incf[y]=min(incf[x],edge[i]);
pre[y]=i;
if(!v[y])v[y]=,q.push(y);
}
}
}
if(d[t]==INF)return false;
else return true;
}
void update()
{
int x=t;
cnt++;
a[cnt].w=d[t];
// cout<<t-1<<"---"<<incf[t]<<"--"<<d[t]<<endl;
a[cnt].flow=incf[t];
while(x!=s)
{
int i=pre[x];
edge[i]-=incf[t];
edge[i^]+=incf[t];
x=ver[i^];
// printf("%d-->",x-1);
}
// cout<<endl;
maxflow+=incf[t];
}
bool check(LL x)
{
LL sum=;
for (int i=; i<=cnt; i++)
{
if (a[i].w<=x)
{
sum+=(LL)a[i].flow*(x-a[i].w+);
}
}
return sum>=k;
}
int main()
{
int uu,vv,c;
while(~scanf("%d%d%lld",&n,&m,&k))
{
cnt=;
tot=;
maxflow=;
s=;
t=n;
memset(head,,sizeof(head));
for (int i=; i<=m; i++)
{
scanf("%d%d%d",&uu,&vv,&c);
add(uu+,vv+,c,);
}
while(spfa())update();
if (k==)
{
printf("0\n");
}
else if (maxflow==){
printf("No solution\n");
}else {
int l=,r=1e9;
while(l<=r)
{
int mid=(l+r)>>;
if (check(mid))
{
r=mid-;
ans=mid;
}
else
{
l=mid+;
}
}
printf("%lld\n",ans);
}
}
return ;
}

HDU-4807-Lunch Time(二分+费用流,思维)的更多相关文章

  1. HDU4807 Lunch Time(费用流变种)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4807 Description The campus of Nanjing Universit ...

  2. HDU 5644 King's Pilots 费用流

    King's Pilots 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5644 Description The military parade w ...

  3. HDU 3667 Transportation(网络流之费用流)

    题目地址:HDU 3667 这题的建图真是巧妙...为了保证流量正好达到k.须要让每一次增广到的流量都是1,这就须要把每一条边的流量都是1才行.可是每条边的流量并非1,该怎么办呢.这个时候能够拆边,反 ...

  4. 【进阶——最小费用最大流】hdu 1533 Going Home (费用流)Pacific Northwest 2004

    题意: 给一个n*m的矩阵,其中由k个人和k个房子,给每个人匹配一个不同的房子,要求所有人走过的曼哈顿距离之和最短. 输入: 多组输入数据. 每组输入数据第一行是两个整型n, m,表示矩阵的长和宽. ...

  5. HDU 3488--Tour(KM or 费用流)

    因为每个点只能经过一次 所以考虑拆点 这题有坑,有重边.. KM算法 把一个点拆成入点和出点 入点在X部,出点在Y步. 如果u,v之间有路径,就在X部的u点连接Y部的v点 求完美匹配. 当完美匹配的时 ...

  6. HDU - 5406 CRB and Apple (费用流)

    题意:对于给定的物品,求两个在高度上单调不递增,权值上单调不递减的序列,使二者长度之和最大. 分析:可以用费用流求解,因为要求长度和最大,视作从源点出发的流量为2的费用流,建负权边,每个物品只能取一次 ...

  7. Lunch Time(费用流变型题,以时间为费用)

    Lunch Time http://acm.hdu.edu.cn/showproblem.php?pid=4807 Time Limit: 4000/2000 MS (Java/Others)     ...

  8. BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]

    3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 960  Solved: 5 ...

  9. BZOJ-3130 费用流 (听题目胡扯丶裸最大流) 二分判定+最大流+实数精度乱搞

    DCrusher爷喜欢A我做的水题,没办法,只能A他做不动的题了.... 3130: [Sdoi2013]费用流 Time Limit: 10 Sec Memory Limit: 128 MBSec ...

随机推荐

  1. 前端(Node.js)(1)-- 初识Node.js

    1.认识 Node.js 诞生.发展.应用现状.生态圈等方面 1.1. 2008年 RyanDahl的目标是创建一个易扩展.适用于现代Web应用通信的服务器平台 1.2.国内外的应用情况 Linked ...

  2. LR11中web_save_timestamp_param

    时间戳是现在时间减去现在的时间 减去 1970年1月1日0点00 的时间 ,然后换算成毫秒. 所以我们需要借助 web_save_timestamp_param 来实现. web_save_times ...

  3. freopen() 函数的使用

    当我们求解acm题目时,通常在设计好算法和程序后,要在调试环境(例如VC等)中运行程序,输入测试数据,当能得到正确运行结果后,才将程序提交到oj中.但由于调试往往不能一次成功,每次运行时,都要重新输入 ...

  4. java并发系列(四)-----源码角度彻底理解ReentrantLock(重入锁)

    1.前言 ReentrantLock可以有公平锁和非公平锁的不同实现,只要在构造它的时候传入不同的布尔值,继续跟进下源码我们就能发现,关键在于实例化内部变量sync的方式不同,如下所示: /** * ...

  5. 使用JSP渲染Web视图

    Pom文件引入以下依赖 注意,创建SpringBoot整合JSP,一定要为war类型,否则会找不到页面 不要把jsp页面存放在Resources目录下,resources目录是给springboot打 ...

  6. Leetcode48. Rotate Image旋转图像

    给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要使用另一个矩阵来旋转图像. 示例 1: 给定 m ...

  7. Django项目:CRM(客户关系管理系统)--10--04PerfectCRM实现King_admin注册功能02

    from django import conf #配置文件print("dj conf:",conf) #配置文件print("dj conf:",conf.s ...

  8. CTSC2016时空旅行

    当时看这道题AC的人数比较多,就开了这道题. 很容易发现是这是一个有关凸包的题. 然后不知道怎么维护凸包,一直在想cdq,感觉复杂度不行,于是被这玩意难住了…… 幸好有亲学长yyh造福人类的题解:ht ...

  9. jquery中的index方法和eq方法

    jquery的index()方法 搜索匹配的元素,并返回相应元素的索引值,从0开始计数,如果不给 .index() 方法传递参数,那么返回值就是这个jQuery对象集合中第一个元素相对于其同辈元素的位 ...

  10. 原型模式 —— Java的赋值、浅克隆和深度克隆的区别

    赋值 直接  = ,克隆 clone 假如说你想复制一个简单变量.很简单: int a= 5; int b= a; b = 6; 这样 a == 5, b == 6 不仅仅是int类型,其它七种原始数 ...