题目描述

有n个点、m条边、和k种商品。第$i$个点可以以$B_{ij}$的价格买入商品$j$,并以$S_{ij}$的价格卖出。任何时候只能持有一个商品。求一个环,使得初始不携带商品时以某种交易方式走过一圈所得的利润/路径长度(向下取整)最大。

输入

第一行包含3个正整数N,M和K,分别表示集市数量、道路数量和商品种类数量。
接下来的N行,第行中包含2K个整数描述一个集市Bi,1 Si,1 Bi,2 Si,2...Bik Si,k。
对于任意的1<=j<=k,整数和分别表示在编号为的集市上购买、卖出编号为的商品时的交易价格。
如果一个交易价格为-1,则表示这个商品在这个集市上不能进行这种交易。
接下来M行,第行包含3个整数Vp,Wp和Tp,表示存在一条从编号为Vp的市场出发前往编号为Wp的市场的路径花费Tp分钟。
1<=N<=100,1<=M<=9900
如果在编号为的集市i中,编号为j的商品既可以购买又可以卖出则0<Si,j<=Bi,j<=10^9
对于编号为P(1<=P<=M)的道路,保证Vp<>Wp且1<=Tp<=10^7
不存在满足1<=P<Q<=M的P,Q,使得(Vp,Wp)=(Vq,Wq) 。

输出

输出包含一个整数,表示盈利效率最高的环路盈利效率,答案向下取整保留到整数。如果没有任何一条环路可以盈利,则输出0。

样例输入

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的更多相关文章

  1. luogu3778/bzoj4898 商旅 (floyd+分数规划+spfa)

    首先floyd求出来每两点间的最短距离,然后再求出来从某点买再到某点卖的最大收益 问题就变成了找到一个和的比值最大的环 所以做分数规划,二分出来那个答案r,把边权变成w[i]-r*l[i],再做spf ...

  2. 洛谷P3778 [APIO2017]商旅——01分数规划

    题目:https://www.luogu.org/problemnew/show/P3778 转化有点技巧: 其实直接关注比率的上下两项,也就是盈利和时间: 通过暴枚和 floyd 可以处理出两两点间 ...

  3. [APIO2017]商旅(floyd+分数规划+SPFA)

    题解:首先肯定要跑最短路,而n<=100,所以可以用floyd,然后根据比值,很容易想到二分答案,然后再SPFA跑一遍负环,就能求出解了. #include<bits/stdc++.h&g ...

  4. BZOJ4898/5367 Apio2017商旅(分数规划+floyd)

    如果要在某点买入某物品并在另一点卖出,肯定是走其间最短路径.于是预处理任意两点间的收益和最短路径,连完边二分答案判负环即可,可以全程floyd.注意inf大小. #include<iostrea ...

  5. 2018.09.09 poj2949Word Rings(01分数规划+spfa判环)

    传送门 这题要先巧妙的转化一下. 对于每个字符串,我们把头尾的两个小字符串对应的点连边,边权是这个字符串的长度. 这样最多会出现26*26个点. 这个时候就只用求出边权和跟边数的最大比值了. 这个显然 ...

  6. Bzoj1486/洛谷P3199 最小圈(0/1分数规划+spfa)/(动态规划+结论)

    题面 Bzoj 洛谷 题解(0/1分数规划+spfa) 考虑\(0/1\)分数规划,设当前枚举到的答案为\(ans\) 则我们要使(其中\(\forall b_i=1\)) \[ \frac{\sum ...

  7. [BZOJ4898] [Apio2017]商旅

    [BZOJ4898] [Apio2017]商旅 传送门 试题分析 考虑两个点之间的路径,显然如果交易的话肯定选\(S_{t,i}-B_{s,i}\)最大的. 那么我们可以先用\(Cost\)把两个点的 ...

  8. POJ 3621 Sightseeing Cows 【01分数规划+spfa判正环】

    题目链接:http://poj.org/problem?id=3621 Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total ...

  9. 【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,然后再判 ...

随机推荐

  1. Swift项目,适配遇到的问题

    Swift4.x 控制器自带xib加载在iOS8系统崩溃 // MARK: - 解决控制器自带xib加载在iOS8系统崩溃的问题.iOS8.x,需要给控制器的xib重写一下init 方法 overri ...

  2. Python 初始—(项目 目录结构)

    在os 包下,给出 import os ,os.path.abspath(__file__)获取当前文件的相对路径,os.path.dirname 获取当前文件所在的文件夹目录 print(os.pa ...

  3. docker镜像文件导入与导出 , 支持批量

    1. 查看镜像id sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE quay.io/calico/node v1.0.1 c70511a ...

  4. 关于PHPExcel 基础使用方法

    $dir=dirname(__FILE__);//找到当前脚本所在路径require_once $dir.'/PHPExcel/PHPExcel.php';$objPHPExcel=new PHPEx ...

  5. Pandas 数据结构Dataframe:基本概念及创建

    "二维数组"Dataframe:是一个表格型的数据结构,包含一组有序的列,其列的值类型可以是数值.字符串.布尔值等. Dataframe中的数据以一个或多个二维块存放,不是列表.字 ...

  6. poj 2674 线性世界 弹性碰撞

    弹性碰撞的题目一般都是指碰到就会掉转方向的一类题目,这里我们可以忽略掉头,仅仅看成擦肩而过,交换名字等等 题意:一条线上N只蚂蚁,每只蚂蚁速度固定,方向和坐标不同,碰头后掉头,求最后掉下去那只蚂蚁的名 ...

  7. spider_main.py

    coding=UTF-8 import html_download import html_outputer import html_parser import url_maneger class S ...

  8. Y86模拟器的安装

    说白了就几个指令,跟实验楼里面并不完全一样. tar -xvf sim.tar cd sim sudo apt-get install tk sudo ln -s /usr/lib/x86_64-li ...

  9. CSS3裁剪与遮罩解析

    一.用途 CSS3裁剪与遮罩(Clipping and Masking)用来隐藏元素的一部分而显示另一部分 二.区别 CSS3裁剪与遮罩(Clipping and Masking)用来隐藏元素的一部分 ...

  10. 13 KNN背景分割器

    传统的前景背景分割方法有GrabCut,分水岭算法,当然也包括一些阈值分割的算法.但是这些算法在应用中往往显得鲁棒性较弱,达不到一个好的分割效果. 现代的背景分割算法融入了机器学习的一些方法来提高分类 ...