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

首先floyd求出来每两点间的最短距离,然后再求出来从某点买再到某点卖的最大收益

问题就变成了找到一个和的比值最大的环

所以做分数规划,二分出来那个答案r,把边权变成w[i]-r*l[i],再做spfa判正环就行了

(本来想偷懒用floyd判正环,结果T了)

  1 #include<bits/stdc++.h>
  2 #define pa pair<int,int>
  3 #define CLR(a,x) memset(a,x,sizeof(a))
  4 using namespace std;
  5 typedef long long ll;
  6 const int maxn=110,maxm=10010,maxk=1010;
  7 const ll inf=1e15;
  8
  9 inline ll rd(){
 10     ll x=0;char c=getchar();int neg=1;
 11     while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();}
 12     while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
 13     return x*neg;
 14 }
 15
 16 int w[maxn][maxn];
 17 int sell[maxn][maxk],buy[maxn][maxk];
 18 int N,M,K,cnt[maxn];
 19 ll dis[maxn][maxn],d[maxn][maxn],dd[maxn];
 20 bool inq[maxn];
 21 queue<int> q;
 22
 23 bool spfa(int s){
 24     while(!q.empty()) q.pop();
 25     dd[s]=0;q.push(s);cnt[s]=1;
 26     while(!q.empty()){
 27         int p=q.front();inq[p]=0;
 28         // printf("%d %d %d\n",p,cnt[p],dd[p]);
 29         q.pop();
 30         for(int b=1;b<=N;b++){
 31             if(d[p][b]==-inf) continue;
 32             if(dd[b]<=dd[p]+d[p][b]){
 33                 dd[b]=dd[p]+d[p][b];
 34                 if(inq[b]) continue;
 35                 if(++cnt[b]>N) return 1;
 36                 q.push(b);
 37                 inq[b]=1;
 38             }
 39         }
 40     }return 0;
 41 }
 42
 43 inline bool judge(ll r){
 44     // printf("%lld:\n",r);
 45     for(int i=1;i<=N;i++){
 46         for(int j=1;j<=N;j++)
 47             d[i][j]=(dis[i][j]==-1)?-inf:w[i][j]-r*dis[i][j];
 48     }
 49     bool re=0;
 50     CLR(cnt,0);CLR(inq,0);
 51     for(int i=1;i<=N;i++) dd[i]=-inf;
 52     for(int i=1;i<=N&&!re;i++){
 53         if(!cnt[i]) re|=spfa(i);
 54     }
 55     return re;
 56 }
 57
 58 int main(){
 59     //freopen("","r",stdin);
 60     int i,j,k;
 61     N=rd(),M=rd(),K=rd();
 62     for(i=1;i<=N;i++){
 63         for(j=1;j<=K;j++){
 64             buy[i][j]=rd(),sell[i][j]=rd();
 65         }
 66     }
 67     for(i=1;i<=N;i++){
 68         for(j=1;j<=N;j++){
 69             if(i==j) continue;
 70             for(k=1;k<=K;k++){
 71                 if(sell[j][k]==-1||buy[i][k]==-1) continue;
 72                 w[i][j]=max(w[i][j],sell[j][k]-buy[i][k]);
 73             }
 74         }
 75     }
 76     CLR(dis,-1);
 77     for(i=1;i<=M;i++){
 78         int a=rd(),b=rd(),c=rd();
 79         dis[a][b]=c;
 80     }
 81     for(i=1;i<=N;i++){
 82         for(j=1;j<=N;j++){
 83             if(dis[j][i]==-1) continue;
 84             for(k=1;k<=N;k++){
 85                 if(dis[i][k]==-1) continue;
 86                 if(dis[j][k]==-1||dis[j][k]>dis[j][i]+dis[i][k])
 87                     dis[j][k]=dis[j][i]+dis[i][k];
 88             }
 89         }
 90     }
 91     // for(i=1;i<=N;i++) for(j=1;j<=N;j++) printf("%d-%d,%lld,%lld\n",i,j,dis[i][j],w[i][j]);
 92
 93     ll l=0,r=inf,ans=0;
 94     while(l<=r){
 95         int m=l+r>>1;
 96         if(judge(m)) ans=m,l=m+1;
 97         else r=m-1;
 98     }
 99     printf("%lld\n",ans);
100     return 0;
101 }

原文地址:https://www.cnblogs.com/Ressed/p/9782095.html

时间: 2024-11-05 12:33:02

luogu3778/bzoj4898 商旅 (floyd+分数规划+spfa)的相关文章

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

题目描述 有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,整数和分别表示在编号为的集市上购买

【bzoj1690】[Usaco2007 Dec]奶牛的旅行 分数规划+Spfa

题目描述 作为对奶牛们辛勤工作的回报,Farmer John决定带她们去附近的大城市玩一天.旅行的前夜,奶牛们在兴奋地讨论如何最好地享受这难得的闲暇. 很幸运地,奶牛们找到了一张详细的城市地图,上面标注了城市中所有L(2 <= L <= 1000)座标志性建筑物(建筑物按1..L顺次编号),以及连接这些建筑物的P(2 <= P <= 5000)条道路.按照计划,那天早上Farmer John会开车将奶牛们送到某个她们指定的建筑物旁边,等奶牛们完成她们的整个旅行并回到出发点后,将她们

【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,然后再判负环,若有负环则调整下界,否则调整上界,直至上下界基本重合. 证明:显然 由于有(c+d)/(a+b+k)>(c+d)/(a+b)≥min(c/a,d/b),所以两个相交环形成的新环一定不是最优解,即答案一定是简单环. 如果存在环使得边权和/点数<mid,那么就有边权和<点数*mid. 又因

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

题目链接:http://poj.org/problem?id=3621 Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11526   Accepted: 3930 Description Farmer John has decided to reward his cows for their hard work by taking them on a tour of the big ci

bzoj1690:[Usaco2007 Dec]奶牛的旅行(分数规划+spfa判负环)

前段时间准备省选没更,后段(?)时间省选考砸没心情更,最近终于开始恢复刷题了... 题目大意:有n个点m条有向边的图,边上有花费,点上有收益,点可以多次经过,但是收益不叠加,边也可以多次经过,但是费用叠加.求一个环使得收益和/花费和最大,输出这个比值. 显然这就是经典的分数规划题啊,就是最优比率环,那么就二分答案,将所有边(u,v)的边权改为[v的点权-(u,v)原边权*mid],这可以算是最优比率环的公式了吧,然后判一下是否有正环,有的话就说明答案可行.判正环有够别扭的,那就全部改成相反数然后

bzoj 1690: [Usaco2007 Dec]奶牛的旅行——分数规划+spfa判负环

Description 作为对奶牛们辛勤工作的回报,Farmer John决定带她们去附近的大城市玩一天.旅行的前夜,奶牛们在兴奋地讨论如何最好地享受这难得的闲暇. 很幸运地,奶牛们找到了一张详细的城市地图,上面标注了城市中所有L(2 <= L <= 1000)座标志性建筑物(建筑物按1..L顺次编号),以及连接这些建筑物的P(2 <= P <= 5000)条道路. 按照计划,那天早上Farmer John会开车将奶牛们送到某个她们指定的建筑物旁边,等奶牛们完成她们的整个旅行并回到

01分数规划+spfa判负环 POJ3621 Sightseeing Cows

Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10348   Accepted: 3539 Description Farmer John has decided to reward his cows for their hard work by taking them on a tour of the big city! The cows must decide how best to

[Usaco2007 Dec][BZOJ1690] 奶牛的旅行|分数规划|二分|SPFA

1690: [Usaco2007 Dec]奶牛的旅行 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 700  Solved: 363[Submit][Status][Discuss] Description 作为对奶牛们辛勤工作的回报,Farmer John决定带她们去附近的大城市玩一天.旅行的前夜,奶牛们在兴奋地讨论如何最好地享受这难得的闲暇. 很幸运地,奶牛们找到了一张详细的城市地图,上面标注了城市中所有L(2 <= L <= 1000)座标志

bzoj1690:[Usaco2007 Dec]奶牛的旅行 (分数规划 &amp;&amp; 二分 &amp;&amp; spfa)

用dfs优化的spfa判环很快啦 分数规划的题目啦 二分寻找最优值,用spfa判断能不能使 Σ(mid * t - p) > 0 最优的情况只能有一个环 因为如果有两个环,两个环都可以作为奶牛的行程,如果两个环单独计算的结果不一样,那么两个环中比值更大的才是最优解,如果结果一样,多算一个环就没有意义了. 代码如下 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 using namespa