【bzoj4898】[Apio2017]商旅 Floyd+分数规划+Spfa
题目描述
有n个点、m条边、和k种商品。第$i$个点可以以$B_{ij}$的价格买入商品$j$,并以$S_{ij}$的价格卖出。任何时候只能持有一个商品。求一个环,使得初始不携带商品时以某种交易方式走过一圈所得的利润/路径长度(向下取整)最大。
输入
输出
样例输入
4 5 2
10 9 5 2
6 4 20 15
9 7 10 9
-1 -1 16 11
1 2 3
2 3 3
1 4 1
4 3 1
3 1 1
样例输出
2
题解
Floyd+分数规划+Spfa
题目显然是一个分数规划的模型,但是如果直接使用分层图模拟商品买卖的过程的话肯定会TLE。
我们不妨换个思路:考虑每件两点之间的连续交易。即在A地购买商品,并在B地卖出的这个过程。
那么这个过程走的一定是最短路,买卖的一定是盈利最大的商品(当无法盈利时显然不进行买卖,盈利为0)。
所以可以使用Floyd求出任意两点之间最短路,再处理出来任意两点之间的最大盈利。
然后就可以对这个图求最大比率环了。二分答案,把每条边的权值看作 最大盈利-最短路*mid ,如果有非负环则说明mid成立,否则mid不成立。
时间复杂度$O(n^2k+n^3\log v)$。
#include <queue>
#include <cstdio>
#include <cstring>
#define N 110
#define K 1010
using namespace std;
typedef long long ll;
queue<int> q;
int n , len[N][N] , val[N][N] , b[N][K] , s[N][K] , inq[N] , num[N];
ll dis[N];
inline bool judge(int mid)
{
int x , i;
while(!q.empty()) q.pop();
for(i = 1 ; i <= n ; i ++ ) dis[i] = inq[i] = num[i] = 0 , q.push(i);
while(!q.empty())
{
x = q.front() , q.pop() , inq[x] = 0;
for(i = 1 ; i <= n ; i ++ )
{
if(dis[i] <= dis[x] + val[x][i] - (ll)mid * len[x][i])
{
dis[i] = dis[x] + val[x][i] - (ll)mid * len[x][i];
if(!inq[i])
{
if(num[i] == n) return 1;
num[i] ++ , inq[i] = 1 , q.push(i);
}
}
}
}
return 0;
}
int main()
{
int m , p , i , j , k , x , y , z , l = 1 , r = 0 , mid , ans = 0;
scanf("%d%d%d" , &n , &m , &p);
for(i = 1 ; i <= n ; i ++ )
for(j = 1 ; j <= p ; j ++ )
scanf("%d%d" , &b[i][j] , &s[i][j]);
for(i = 1 ; i <= n ; i ++ )
for(j = 1 ; j <= n ; j ++ )
for(k = 1 ; k <= p ; k ++ )
if(~b[i][k] && ~s[j][k])
val[i][j] = max(val[i][j] , s[j][k] - b[i][k]);
memset(len , 0x3f , sizeof(len));
for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &x , &y , &z) , len[x][y] = z , r = max(r , z);
for(k = 1 ; k <= n ; k ++ )
for(i = 1 ; i <= n ; i ++ )
for(j = 1 ; j <= n ; j ++ )
len[i][j] = min(len[i][j] , len[i][k] + len[k][j]);
while(l <= r)
{
mid = (l + r) >> 1;
if(judge(mid)) ans = mid , l = mid + 1;
else r = mid - 1;
}
printf("%d\n" , ans);
return 0;
}
【bzoj4898】[Apio2017]商旅 Floyd+分数规划+Spfa的更多相关文章
- luogu3778/bzoj4898 商旅 (floyd+分数规划+spfa)
首先floyd求出来每两点间的最短距离,然后再求出来从某点买再到某点卖的最大收益 问题就变成了找到一个和的比值最大的环 所以做分数规划,二分出来那个答案r,把边权变成w[i]-r*l[i],再做spf ...
- 洛谷P3778 [APIO2017]商旅——01分数规划
题目:https://www.luogu.org/problemnew/show/P3778 转化有点技巧: 其实直接关注比率的上下两项,也就是盈利和时间: 通过暴枚和 floyd 可以处理出两两点间 ...
- [APIO2017]商旅(floyd+分数规划+SPFA)
题解:首先肯定要跑最短路,而n<=100,所以可以用floyd,然后根据比值,很容易想到二分答案,然后再SPFA跑一遍负环,就能求出解了. #include<bits/stdc++.h&g ...
- BZOJ4898/5367 Apio2017商旅(分数规划+floyd)
如果要在某点买入某物品并在另一点卖出,肯定是走其间最短路径.于是预处理任意两点间的收益和最短路径,连完边二分答案判负环即可,可以全程floyd.注意inf大小. #include<iostrea ...
- 2018.09.09 poj2949Word Rings(01分数规划+spfa判环)
传送门 这题要先巧妙的转化一下. 对于每个字符串,我们把头尾的两个小字符串对应的点连边,边权是这个字符串的长度. 这样最多会出现26*26个点. 这个时候就只用求出边权和跟边数的最大比值了. 这个显然 ...
- Bzoj1486/洛谷P3199 最小圈(0/1分数规划+spfa)/(动态规划+结论)
题面 Bzoj 洛谷 题解(0/1分数规划+spfa) 考虑\(0/1\)分数规划,设当前枚举到的答案为\(ans\) 则我们要使(其中\(\forall b_i=1\)) \[ \frac{\sum ...
- [BZOJ4898] [Apio2017]商旅
[BZOJ4898] [Apio2017]商旅 传送门 试题分析 考虑两个点之间的路径,显然如果交易的话肯定选\(S_{t,i}-B_{s,i}\)最大的. 那么我们可以先用\(Cost\)把两个点的 ...
- POJ 3621 Sightseeing Cows 【01分数规划+spfa判正环】
题目链接:http://poj.org/problem?id=3621 Sightseeing Cows Time Limit: 1000MS Memory Limit: 65536K Total ...
- 【bzoj1486】[HNOI2009]最小圈 分数规划+Spfa
题目描述 样例输入 4 5 1 2 5 2 3 5 3 1 5 2 4 3 4 1 3 样例输出 3.66666667 题解 分数规划+Spfa判负环 二分答案mid,并将所有边权减去mid,然后再判 ...
随机推荐
- 字符串替换For linux C
1.临时空间给了个1024,不需要可减少长度. 2.结果只用用strcpy了,没校验. bool Replace(char *str,const char *src, const char *des) ...
- OceanBase安装
背景: OceanBase是阿里巴巴.蚂蚁金服自主研发的可扩展的分布式关系数据库,实现了数千亿条记录.数百 TB 数据上的跨行跨表事务,主要支持支付宝核心的交易.支付.会员和账务系统等 OLTP 和 ...
- (转)基于REST架构的Web Service设计
原文出处:http://www.williamlong.info/archives/1728.html ------------------------------------------------ ...
- python__标准库 : 正则表达式(re)
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none. re.search 扫描整个字符串并返回第一个成功的匹配. 替换: re.sub(p ...
- python__基础 : 类的 __slots__ 方法
实例在创建出来之后,可以动态的添加属性和方法, 那如果想要限制添加的实例属性,可以用一下 __slots__ 这个东西: class Test(object): __slots__ = ('name' ...
- C语言进阶—— 逻辑运算符分析15
印象中的逻辑运算符: ---学生:老师,在我的印象中,逻辑运算符用在条件判断的时候,真挺简单的,还有必要深究吗? ---老师:逻辑运算符确实在条件判断的时候用的比较多,但是并不能说简单... 请思考下 ...
- react+redux状态管理实现排序 合并多个reducer文件
这个demo只有一个reducer 所以合并reducer这个demo用不到 ,但是我写出来这样大家以后可以用到,很好用,管理多个reducer,因为只要用到redux就不会只有一个reducer所以 ...
- python sys模块和序列化模块
sys模块是与python解释器交互的一个接口: sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit( ...
- DbVisualizer 解决中文乱码问题
在SQL Commander中,sql语句中如果有中文,显示是‘口口口’. 解决办法如下: 在Tools->tool Properties->General->Appearance- ...
- 【转】Git命令解说
3.12. Git branch 3.12.1. 总述 当第一次执行git init时,系统就会创建一个名为“master”的分支. 而其它分支则通过手工创建. 下面列举一些常见的分支策略: ...