~~~题面~~~

题解:

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. 深入解析UUID及其应用(转载)

    UUID 编辑 UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software Founda ...

  2. 探索 Flask

    探索 Flask 探索 Flask 是一本关于使用 Flask 开发 Web 应用程序的最佳实践和模式的书籍.这本书是由 426 名赞助人 在 Kickstarter 上 于 2013 年 7 月资助 ...

  3. Appium最新的服务器初始化参数(Capability)【截止11月29日,后续最新的可以看github】

    键 描述 值 automationName 自动化测试的引擎 Appium (默认)或者 Selendroid platformName 使用的手机操作系统 iOS, Android, 或者 Fire ...

  4. C++11 type_traits 之is_convertible源码分析

    请看源码: struct __sfinae_types { typedef char __one; typedef ]; } __two; }; template<typename _From, ...

  5. 407. Plus One【LintCode java】

    Description Given a non-negative number represented as an array of digits, plus one to the number. T ...

  6. EF中如何为表添加新的字段和映射

    首先先了解一下ef生成的模型edmx的代码,传送门:http://www.cnblogs.com/yushengbo/p/4807715.html 一.添加新的字段 例子就用我现在项目的这个吧,首先在 ...

  7. Python3 Tkinter-Button

    1.绑定事件处理函数 from tkinter import * def hello(): print('Hello!') root=Tk() button=Button(root,text='cli ...

  8. 【转】redis安装与配置

    一.安装 1.官方:http://www.redis.cn/download.html 2.下载.解压.编译 wget http://download.redis.io/releases/redis- ...

  9. Sum of Consecutive Prime Numbers(素数打表+尺取)

    Description Some positive integers can be represented by a sum of one or more consecutive prime numb ...

  10. 20145214 《Java程序设计》第2周学习总结

    20145214 <Java程序设计>第2周学习总结 教材学习内容总结 基本类型 整数:可分为short整数.int整数.long整数. 字节:即byte类型,可表示-128~127的整数 ...