~~~题面~~~

题解:

upd: 在洛谷上被Hack了。。。思路应该是对的,代码就别看了

感觉有个地方还是非常妙的,就是因为在x买东西,在y卖出,就相当于直接从x走向了y,因为经过中间的城市反正也不会造成任何影响。

所以建图就可以直接把所有城市两两连边,然后直接枚举找出使得在x买东西,在y卖出的利润最大化的物品,并将利润作为权值,(a[i])

再floyd找出x到y的最短路径(这大概就算用到城市可以重复经过的条件了吧)作为代价,(b[i])

接下来就和[HNOI2009]最小圈非常类似了。

只不过这里是要找最大利润,而我们是用spfa找负环,所以可以对边权取相反数,(当然你也可以不变边权找正环)

此外还有一个需要注意的地方,

如果你是二分小数自然没有任何问题,

但是如果你是二分整数就要注意判断0环了(因为答案是向下取整的),因为如果你二分小数的话,反正你会多二分几次来保证精度,所以不判断是没有什么问题的,

但是整数不一样,所以要判断0环,方法也很简单,在dfs版spfa里面的判断条件上加上=就可以了

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 150
#define ac 21000
#define getchar() *o++
#define inf 2139062143
char READ[],*o=READ;
int n,m,l,mid,maxn;
int buy[AC][AC*],sale[AC][AC*],s[AC][AC],f[AC][AC],dis[ac];
int date[ac],Next[ac],Head[AC],length[ac],tot;
bool vis[AC],flag;
/*想了很久如何处理异地交易的问题,因为中间走过的路程会被忽略,
所以实际上就相当于直接从买入地x走到了卖出地y,
所以直接两两连边,因为反正可以重复经过,所以走一条边就相当于略过了中间的所有边,
然后为了尽量节省时间,所以先处理出任意两点之间的最短路,因为不管怎么走收益不变,
但代价变了,所以连边要连最短路,所以先floyd处理一下,再把结果连成边,
不过利益不变的前提是买同一种商品,但是商品不止一种,所以还要处理出最大收益,
因为地点都已经固定了,所以这个时候就只要枚举一下买哪种划得来了,
标准就是买卖单个的收入就行了
然后动态改一下权值就好了,dfs版spfa找负环*/
inline int read()
{
int x=;char c=getchar();bool z=false;
while(c > '' || c < '') {if(c == '-') z=true; c=getchar();}
while(c >= '' && c <= '') x=x*+c-'',c=getchar();
if(!z) return x;
else return -x;
} inline void add(int f,int w)
{
date[++tot]=w,Next[tot]=Head[f],Head[f]=tot;
} inline void upmin(int &a,int b)
{
if(b < a) a = b;
} inline void upmax(int &a,int b)
{
if(b > a) a = b;
} void pre()
{
int a,b,c;
n=read(),m=read(),l=read();
memset(f,,sizeof(f));
for(R i=;i<=n;i++)
{
f[i][i]=;
for(R j=;j<=l;j++)
buy[i][j]=read() , sale[i][j]=read();
}
for(R i=;i<=m;i++)
{
a=read(),b=read(),c=read();
upmin(f[a][b],c);//这里就要upmin。,,,,不然可能会被不优的边覆盖
}
} void init()
{
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",f[i][j]);
printf("\n");
}
printf("!!!\n");*/
for(R k=;k<=n;k++)
for(R i=;i<=n;i++)
{
if(f[i][k] == inf) continue;
for(R j=;j<=n;j++)
if(f[k][j] != inf) upmin(f[i][j] , f[i][k] + f[k][j]);
}//怕爆了
for(R i=;i<=n;i++)//枚举起点
for(R j=;j<=n;j++)//枚举终点
{
if(i == j) continue;
if(f[i][j] == inf) continue;
for(R k=;k<=l;k++) //枚举买哪种
{
if(sale[j][k] == - || buy[i][k] == -) continue;
upmax(s[i][j],sale[j][k] - buy[i][k]);//获取利润
upmax(maxn,s[i][j] / f[i][j]);
}
}
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",f[i][j]);
printf("\n");
}
// printf("---------------\n");
printf("\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%d ",s[i][j]);
printf("\n");
}*/
for(R i=;i<=n;i++)
for(R j=;j<=n;j++)
{
if(i == j) continue;
if(f[i][j] == inf) continue;//error,,,这里不能加上!s[i][j],虽然没有利润,但仍然可以起到连接作用
add(i,j);
}
} void spfa(int x)
{
int now;
vis[x]=true;
for(R i=Head[x]; i ;i=Next[i])
{
now=date[i];
if(dis[now] >= dis[x] + length[i])//找负环肯定是最短路啊
{//加个等号判0环?
if(vis[now]) {flag=true;break;}
dis[now] = dis[x] + length[i];
spfa(now);
}
}
vis[x]=false;
} bool check()
{
int now;
flag=false;
memset(dis,,sizeof(dis));
for(R i=;i<=n;i++)
for(R j=Head[i]; j ;j=Next[j])
{
now=date[j];
length[j]=mid * f[i][now] - s[i][now];//因为要用找负环的方法找正环,所以边权取相反
}//error,,是f[i][now]
for(R i=;i<=n;i++)
{
spfa(i);
if(flag) return true;
}
return false;
} void half()
{
int l=,r=maxn;
while(r - l > )
{
mid=(l + r) / ;
if(check()) l=mid;
else r=mid;
}
if(r > l)
{
mid=r;
if(check()) printf("%d\n",r);
else printf("%d\n",l);
}
else printf("%d\n",l);
} int main()
{
// freopen("in.in","r",stdin);
fread(READ,,,stdin);
pre();
init();
half();
// fclose(stdin);
return ;
}

[APIO2017]商旅 0/1分数规划的更多相关文章

  1. bzoj 4898: [Apio2017]商旅【Floyd+分数规划+二分】

    其实并不会分数规划 因为要最大化 ans=总收益/总路程 ,所以考虑二分答案,找到一条 ans<=总收益/总路程 的回路.先预处理出d(i,j)为(i,j)最短路,w(i,j)为在i买某个物品在 ...

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

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

  3. poj 2976 Dropping tests 0/1分数规划

    0/1分数规划问题,用二分解决!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> # ...

  4. bzoj 3597: [Scoi2014]方伯伯运椰子 0/1分数规划

    3597: [Scoi2014]方伯伯运椰子 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 144  Solved: 78[Submit][Status ...

  5. LOJ 3089 「BJOI2019」奥术神杖——AC自动机DP+0/1分数规划

    题目:https://loj.ac/problem/3089 没想到把根号之类的求对数变成算数平均值.写了个只能得15分的暴力. #include<cstdio> #include< ...

  6. poj2728 Desert King【最优比率生成树】【Prim】【0/1分数规划】

    含[最小生成树Prim]模板. Prim复杂度为$O(n^2),适用于稠密图,特别是完全图的最小生成树的求解.   Desert King Time Limit: 3000MS   Memory Li ...

  7. POJ - 2976 Dropping tests && 0/1 分数规划

    POJ - 2976 Dropping tests 你有 \(n\) 次考试成绩, 定义考试平均成绩为 \[\frac{\sum_{i = 1}^{n} a_{i}}{\sum_{i = 1}^{n} ...

  8. [SDOI2017]新生舞会 0/1分数规划

    ---题面--- 题解: 0/1分数规划,,,但是竟然有诡异的精度问题???因为这个被卡了好久 中途还写过一次KM,,,结果陷入死循环,,,我大概是写了一个假KM,,,于是放弃KM,回来调费用流 这个 ...

  9. bzoj3232圈地游戏——0/1分数规划+差分建模+判环

    Description DZY家的后院有一块地,由N行M列的方格组成,格子内种的菜有一定的价值,并且每一条单位长度的格线有一定的费用. DZY喜欢在地里散步.他总是从任意一个格点出发,沿着格线行走直到 ...

随机推荐

  1. spring-boot、spring-data-jpa、hibernate整合

    一.Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置. ...

  2. Spring Cloud 熔断机制 -- 断路器

    Spring Cloud 入门教程(七): 熔断机制 -- 断路器 对断路器模式不太清楚的话,可以参看另一篇博文:断路器(Curcuit Breaker)模式,下面直接介绍Spring Cloud的断 ...

  3. vim程序员加强功能

    1.折叠      1.1折叠的方式有六种           manual:以标准的vim结构定义折叠跨越的范围,类似移动命令           indent:折叠与折叠的层次,对应于文本的缩排与 ...

  4. java 多维数组转化为字符串

    int[][] a = {{1,2,3},{4,5,7}}; System.out.println(Arrays.deepToString(a)); Arrays.deepToString()此方法是 ...

  5. Unity Shader学习笔记 - 用UV动画实现沙滩上的泡沫

    这个泡沫效果来自远古时代的Unity官方海岛Demo, 原效果直接复制3个材质球在js脚本中做UV动画偏移,这里尝试在shader中做动画并且一个pass中完成: // Upgrade NOTE: r ...

  6. Tensorflow中使用tfrecord方式读取数据-深度学习-周振洋

    本博客默认读者对神经网络与Tensorflow有一定了解,对其中的一些术语不再做具体解释.并且本博客主要以图片数据为例进行介绍,如有错误,敬请斧正. 使用Tensorflow训练神经网络时,我们可以用 ...

  7. 隐马尔科夫模型(hidden Markov Model)

    万事开头难啊,刚开头确实不知道该怎么写才能比较有水平,这篇博客可能会比较长,隐马尔科夫模型将会从以下几个方面进行叙述:1 隐马尔科夫模型的概率计算法  2 隐马尔科夫模型的学习算法 3 隐马尔科夫模型 ...

  8. LiveVideoStack Meet|深圳 多媒体开发新趋势

    2018年初始,音视频技术生态并不平静,Codec争夺愈加激烈,新一代标准的挑战一浪高过一浪:WebRTC的定版也为打通浏览器.移动端乃至IoT带来了机会:此外AI.区块链技术的兴起,催化着与多媒体领 ...

  9. 安装sqoop 1.99.4

    参考http://sqoop.apache.org/docs/1.99.4/Installation.html 1.简介 sqoop2分为server和client两部分.server作为maprde ...

  10. BZOJ 4176 Lucas的数论 莫比乌斯反演+杜教筛

    题意概述:求,n<=10^9,其中d(n)表示n的约数个数. 分析: 首先想要快速计算上面的柿子就要先把d(ij)表示出来,有个神奇的结论: 证明:当且仅当a,b没有相同的质因数的时候我们统计其 ...