题目链接:

[APIO2017]商旅

枚举任意两个点$(s,t)$,求出在$s$买入一个物品并在$t$卖出的最大收益。

新建一条从$s$到$t$的边,边权为最大收益,长度为原图从$s$到$t$的最短路,最短路用$floyd$求即可。

对于原图的边,边权为$0$,长度为输入长度。

对于新图,需要找到一个环使得换上边的边权和比长度和最大。

显然二分答案然后分数规划,之后就变成了判断图中是否有负环,用SPFA判负环即可。

注意此题卡精,需要使用$long\ double$。

  1. #include<set>
  2. #include<map>
  3. #include<queue>
  4. #include<stack>
  5. #include<cmath>
  6. #include<vector>
  7. #include<cstdio>
  8. #include<bitset>
  9. #include<cstring>
  10. #include<iostream>
  11. #include<algorithm>
  12. #define ll long long
  13. #define ld long double
  14. using namespace std;
  15. const double eps=1e-10;
  16. char *p1,*p2,buf[100000];
  17. #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
  18. int read() {int x=0,flag=1; char c=nc();if(c=='-'){flag=-1,c=nc();} while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return flag*x;}
  19. int f[110][110];
  20. int head[110];
  21. int next[200000];
  22. int to[200000];
  23. int a[200000];
  24. int b[200000];
  25. ld v[200000];
  26. int vis[110];
  27. int cnt[110];
  28. queue<int>que;
  29. int s[110][1010];
  30. int t[110][1010];
  31. int tot;
  32. int n,m,q;
  33. int x,y,z;
  34. ld ans;
  35. ld dis[110];
  36. void add(int x,int y,int w,int z)
  37. {
  38. next[++tot]=head[x];
  39. head[x]=tot;
  40. to[tot]=y;
  41. a[tot]=w;
  42. b[tot]=z;
  43. }
  44. bool SPFA(int S)
  45. {
  46. dis[S]=0;
  47. que.push(S);
  48. vis[S]=1;
  49. while(!que.empty())
  50. {
  51. int now=que.front();
  52. que.pop();
  53. vis[now]=0;
  54. for(int i=head[now];i;i=next[i])
  55. {
  56. if(dis[to[i]]>dis[now]+v[i])
  57. {
  58. dis[to[i]]=dis[now]+v[i];
  59. cnt[to[i]]=cnt[now]+1;
  60. if(cnt[to[i]]>150)
  61. {
  62. return true;
  63. }
  64. if(!vis[to[i]])
  65. {
  66. vis[to[i]]=1;
  67. que.push(to[i]);
  68. }
  69. }
  70. }
  71. }
  72. return false;
  73. }
  74. int main()
  75. {
  76. n=read();m=read();q=read();
  77. for(int i=1;i<=n;i++)
  78. {
  79. for(int j=1;j<=q;j++)
  80. {
  81. s[i][j]=read();t[i][j]=read();
  82. }
  83. }
  84. memset(f,0x3f,sizeof(f));
  85. for(int i=1;i<=m;i++)
  86. {
  87. x=read();y=read();z=read();
  88. f[x][y]=min(f[x][y],z);
  89. add(x,y,0,z);
  90. }
  91. for(int k=1;k<=n;k++)
  92. {
  93. for(int i=1;i<=n;i++)
  94. {
  95. for(int j=1;j<=n;j++)
  96. {
  97. f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
  98. }
  99. }
  100. }
  101. for(int i=1;i<=n;i++)
  102. {
  103. for(int j=1;j<=n;j++)
  104. {
  105. if(f[i][j]==0x3f)continue;
  106. int mx=-1;
  107. for(int k=1;k<=q;k++)
  108. {
  109. int num;
  110. if(s[i][k]==-1||t[j][k]==-1||s[i][k]>=t[j][k])continue;
  111. else num=t[j][k]-s[i][k];
  112. mx=max(mx,num);
  113. }
  114. if(mx==-1)continue;
  115. add(i,j,mx,f[i][j]);
  116. }
  117. }
  118. ld l=0,r=1e12;
  119. ans=-1;
  120. while(r-l>=eps)
  121. {
  122. ld mid=(l+r)/2;
  123. for(int i=1;i<=tot;i++)
  124. {
  125. v[i]=mid*b[i]-a[i];
  126. }
  127. for(int i=1;i<=n;i++)
  128. {
  129. dis[i]=0;
  130. vis[i]=cnt[i]=0;
  131. }
  132. int flag=0;
  133. for(int i=1;i<=n;i++)
  134. {
  135. if(dis[i]==0)
  136. {
  137. if(SPFA(i))
  138. {
  139. l=mid;
  140. ans=mid;
  141. flag=1;
  142. break;
  143. }
  144. }
  145. }
  146. if(!flag)
  147. {
  148. r=mid;
  149. }
  150. }
  151. printf("%lld",ans==-1?0ll:(ll)(ans+eps));
  152. }

[APIO2017]商旅——分数优化+floyd+SPFA判负环+二分答案的更多相关文章

  1. 【HNOI2009】最小圈 题解(SPFA判负环+二分答案)

    前言:模拟赛考试题,不会做,写了个爆搜滚蛋仍然保龄. --------------------- 题目链接 题目大意:给定一张有向图,求一个环,使得这个环的长度与这个环的大小(所含结点个数)的比值最小 ...

  2. BZOJ 4898 [APIO2017] 商旅 | SPFA判负环 分数规划

    BZOJ 4898 [APIO2017] 商旅 | SPFA判负环 分数规划 更清真的题面链接:https://files.cnblogs.com/files/winmt/merchant%28zh_ ...

  3. [HNOI2009]最小圈 分数规划 spfa判负环

    [HNOI2009]最小圈 分数规划 spfa判负环 题面 思路难,代码简单. 题目求圈上最小平均值,问题可看为一个0/1规划问题,每个边有\(a[i],b[i]\)两个属性,\(a[i]=w(u,v ...

  4. 2018.09.24 bzoj1486: [HNOI2009]最小圈(01分数规划+spfa判负环)

    传送门 答案只保留了6位小数WA了两次233. 这就是一个简单的01分数规划. 直接二分答案,根据图中有没有负环存在进行调整. 注意二分边界. 另外dfs版spfa判负环真心快很多. 代码: #inc ...

  5. [P1768]天路(分数规划+SPFA判负环)

    题目描述 “那是一条神奇的天路诶~,把第一个神犇送上天堂~”,XDM先生唱着这首“亲切”的歌曲,一道猥琐题目的灵感在脑中出现了. 和C_SUNSHINE大神商量后,这道猥琐的题目终于出现在本次试题上了 ...

  6. spfa判负环

    bfs版spfa void spfa(){ queue<int> q; ;i<=n;i++) dis[i]=inf; q.push();dis[]=;vis[]=; while(!q ...

  7. POJ 3259 Wormholes(SPFA判负环)

    题目链接:http://poj.org/problem?id=3259 题目大意是给你n个点,m条双向边,w条负权单向边.问你是否有负环(虫洞). 这个就是spfa判负环的模版题,中间的cnt数组就是 ...

  8. Poj 3259 Wormholes(spfa判负环)

    Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 42366 Accepted: 15560 传送门 Descr ...

  9. poj 1364 King(线性差分约束+超级源点+spfa判负环)

    King Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14791   Accepted: 5226 Description ...

随机推荐

  1. Sublim text 3 同步 eclipse 快捷键

    首选项>按键绑定>用户 配置内容(注意为JSON格式!) [ { "keys": ["shift+enter"], "command&qu ...

  2. jenkins pipline

    def getHost(){ def remote = [:] remote.name = 'server02' remote.host = '39.19.90' remote.user = 'roo ...

  3. fatfs源码阅读

    使用fatfs文件的第一步,就是调用F_mount函数注册一个工作空间. F_mount函数的原型如下: 第一个参数根据网上大神的答复,是外设类型,如果是sd卡就是0,flash等等其他的外设就是其他 ...

  4. Python函数Day3

    一.函数名的应用 函数名类似于特殊的变量,打印函数名就是打印函数的内存地址 ① 函数名就是函数的内存地址 def func(): pass >>>func <function ...

  5. cdh-hbase用户无法执行命令

  6. Linux命令——ps、pstree

    转载请注明出处:https://www.cnblogs.com/kelamoyujuzhen/p/9814883.html ps 简介 ps(processes status)是Unix / Linu ...

  7. C++(三十四) — 友元函数、友元类

    友元是可以访问类的私有成员和保护成员的外部函数.由 friend 修饰,不是本类的成员函数,但是在它的函数体中可以通过对象名访问本类的私有和保护成员.     友元关系不可传递,且是单向的.    友 ...

  8. (2) openstack--keystone

    yun1 OpenStack packages yum install python-openstackclient -y yum install openstack-selinux SQL data ...

  9. 运输层6——TCP可靠传输的实现

    目录 1. 以字节为单位的滑动窗口 2. 超时重传时间的选择 写在前面:本文章是针对<计算机网络第七版>的学习笔记 运输层1--运输层协议概述 运输层2--用户数据报协议UDP 运输层3- ...

  10. 链表(python)

    链表1.为什么需要链表顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁,所以使用起来并不是很灵活.链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理. ...