Portal -->bzoj4898

Solution

​  这题的话。。首先答案的形式应该是\(01\)分数规划了

​  然后比较关键的一步在于,我们需要简化一下交易的过程

​  具体一点就是,我们将中间经过的不交易的点和路径全部”合并“起来,只考虑买入物品和卖出物品的两个点

​  首先看一下这两个点之间的路程应该怎么走

​  因为路程长度是做分母的那个,所以我们肯定希望在到达同一个点的情况下走最短路,那所以这两个点一旦确定下来了,路程也就确定下来了

​  两两之间最短路的求解因为\(N\)比较小所以可以直接用floyd解决

​  

​  然后接下来就是交易的物品我们要选择哪一个

​  很明显是选盈利最大的那个,大力贪心就好了ovo

​  所以总的来说,如果确定了进行买卖的两个点,我们走的路程一定是最短路,买卖的一定是这两个点能够交易的所有物品中,盈利最大的那个

​  

​  记两点间最短路为\(w_{i,j}\),最优的盈利为\(val_{i,j}\),那么套用分数规划的套路(Portal -->【learning】),我们需要快速求出一个环的:

\[max(\sum val_{i,j}-\lambda' \sum w_{i,j})
\]

​​  与\(0\)的大小关系

​​  那么这个其实就直接用spfa判断是否有正环就好了

​  

​  自己跳进去的坑:

​  ​  额。。注意到这里题目说的是**利润/路径长度(向下取整) **的最大值。。

​  ​  所以!在二分答案的时候!\(l\)和\(r\)和\(mid\)用int就好了!! QWQ

​  ​  以及\(K\)的范围是\(1000\)而不是\(100\)。。。

​  

​  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=110,M=9910,inf=2147483647;
const double eps=1e-8;
struct xxx{
int y,x,nxt;
double w;
}a[N*N*2];
struct Data{
int y,x;
int w;
}rec[N*N*2];
queue<int> q;
int h[N],cnt[N],buy[N][1010],sell[N][1010],w[N][N];
double val[N];
bool vis[N];
int n,m,K,tot,rec_cnt;
void add(int x,int y,double val);
bool spfa();
void build(double mid);
bool check(double mid);
void prework();
void floyd();
void solve(); int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%d%d%d",&n,&m,&K);
for (int i=1;i<=n;++i)
for (int j=1;j<=K;++j)
scanf("%d%d",&buy[i][j],&sell[i][j]);
int x,y,w1;
rec_cnt=0;
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
w[i][j]=inf;
for (int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&w1);
rec[++rec_cnt].x=x; rec[rec_cnt].y=y; rec[rec_cnt].w=0;
w[x][y]=min(w[x][y],w1);
}
prework();
solve();
} void add(int x,int y,double val){
//printf("%d %d %.3lf\n",x,y,val);
a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot; a[tot].w=val;
} bool spfa(){
while (!q.empty()) q.pop();
int u,v;
for (int i=1;i<=n;++i) vis[i]=true,q.push(i),cnt[i]=0,val[i]=0;
while (!q.empty()){
v=q.front(); q.pop();
for (int i=h[v];i!=-1;i=a[i].nxt){
u=a[i].y;
if (val[u]<=val[v]+a[i].w){
val[u]=val[v]+a[i].w;
if (!vis[u]){
q.push(u),vis[u]=true,++cnt[u];
if (cnt[u]>n) return true;
}
}
}
vis[v]=false;
}
return false;
} bool check(double mid){
build(mid);
return spfa();
} void build(double mid){
tot=0;
for (int i=1;i<=n;++i) h[i]=-1;
for (int i=1;i<=rec_cnt;++i)
add(rec[i].x,rec[i].y,1.0*rec[i].w-mid*w[rec[i].x][rec[i].y]);
} void floyd(){
for (int k=1;k<=n;++k)
for (int i=1;i<=n;++i){
if (w[i][k]==inf) continue;
for (int j=1;j<=n;++j)
if (w[k][j]!=inf)
w[i][j]=min(w[i][j],w[i][k]+w[k][j]);
}
} void prework(){
floyd();
int mx,tmp;
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j){
if (w[i][j]==inf) continue;
mx=0;
for (int k=1;k<=K;++k)
if (buy[i][k]!=-1&&sell[j][k]!=-1){
if (sell[j][k]-buy[i][k]>mx) tmp=k;
mx=max(mx,sell[j][k]-buy[i][k]);
}
if (mx)
rec[++rec_cnt].x=i,rec[rec_cnt].y=j,rec[rec_cnt].w=mx;
}
} void solve(){
int l=0,r=1e9,mid,ans;
while (l<=r){
mid=(l+r)>>1;
if (check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
}

【bzoj4898】商旅的更多相关文章

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

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

  2. 【learning】01分数规划

    问题描述 首先分数规划是一类决策性问题 一般形式是: \[ \lambda=\frac{f(x)}{g(x)} \] 其中\(f(x)\)和\(g(x)\)都是连续的实值函数,然后要求\(\lambd ...

  3. [BZOJ4898] [Apio2017]商旅

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

  4. 【BZOJ4898】[Apio2017]商旅 分数规划+SPFA

    [BZOJ4898][Apio2017]商旅 Description 在广阔的澳大利亚内陆地区长途跋涉后,你孤身一人带着一个背包来到了科巴.你被这个城市发达而美丽的市场所深深吸引,决定定居于此,做一个 ...

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

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

  6. BZOJ4898 & BZOJ5367 & 洛谷3778:[APIO2017]商旅——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4898 https://www.lydsy.com/JudgeOnline/problem.php? ...

  7. 【bzoj4898】[Apio2017]商旅 Floyd+分数规划+Spfa

    题目描述 有n个点.m条边.和k种商品.第$i$个点可以以$B_{ij}$的价格买入商品$j$,并以$S_{ij}$的价格卖出.任何时候只能持有一个商品.求一个环,使得初始不携带商品时以某种交易方式走 ...

  8. bzoj4898 & loj2308 [Apio2017]商旅 最短路+01分数规划

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4898 https://loj.ac/problem/2308 题解 发现我们可以把整个环路分成 ...

  9. 「APIO2017」商旅

    「APIO2017」商旅 题目描述 在广阔的澳大利亚内陆地区长途跋涉后,你孤身一人带着一个背包来到了科巴.你被这个城市发达而美丽的市场所深深吸引,决定定居于此,做一个商人.科巴有 \(N\) 个集市, ...

随机推荐

  1. Unity Lighting - Emissive Materials 自发光材质(九)

      Emissive Materials 自发光材质 Whilst Area Lights are not supported by Precomputed Realtime GI, similar ...

  2. 从零开始的Python学习Episode 10——函数

    函数 一.函数的创建 简单格式 def function_name(参数表): 函数体 return 如果没有写return,函数会默认返回一个none 二.函数的参数 必需参数: 调用函数时必需参数 ...

  3. Catch That Cow:BFS:加标记数组:不加标记数组

    Catch That Cow Problem Description Farmer John has been informed of the location of a fugitive cow a ...

  4. Python基础灬补充(循环、格式化输出)

    for循环&格式化输出 chinese_zodiac = '鼠牛虎兔龙蛇马羊猴鸡狗猪' for year in range(2000, 2013): print("%s年的生肖是:% ...

  5. Node2vec 代码分析

    Node2vec 代码从Github上clone到本地,主要是main.py和node2vec.py两个文件. 下面把我的读代码注释放到上面来, import numpy as np import n ...

  6. JDBC及DBUtils

    1.JDBC2.DBUtils ###01JDBC概念和数据库驱动程序 * A: JDBC概念和数据库驱动程序 * a: JDBC概述 * JDBC(Java Data Base Connectivi ...

  7. List<T>.Distinct()

    )            }; //使用匿名方法            List<Person> delegateList = personList.Distinct(new Compar ...

  8. Python常用模块之hashlib

    Python里面的hashlib模块提供了很多加密的算法,这里介绍一下hashlib的简单使用事例,用hashlib的md5算法加密数据 import hashlib hash = hashlib.m ...

  9. c语言的知识与能力自评

    知识与能力 C语言最早是由美国Bell实验室设计的,主要用作UNIX系统的工作语言,后来发展成为一种通用语言.C与UNIX有密切的关系,C最早是在PDP机器上用UNIX操作系统上开发的,后来又用C语言 ...

  10. rabbitmqctl 的常用命令

    # 查看服务器的状态 rabbitmqctl status   # 查看环境变量 rabbitmqctl environment   # 停止rabbitmq的应用 rabbitmqctl stop_ ...