最优贸易

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最优贸易相关的知识,希望对你有一定的参考价值。

原题链接:https://www.luogu.org/problem/show?pid=1073#sub

猛的一看这题,诶我怎么在哪见过。。

哦是双向SPFA那题。。然后凭记忆xjb搞了一下就A了。。

翻了一下我codevs的记录,诶我在半年之前写过这题?我怎么不记得了?

坑点略多就是了。。有些地方必须用奇怪的写法才可以,否则绝对爆0。。。。

这题题意要求我们求出能赚取的最大差价。说到差价很好想了,肯定是卖出价-买入价=差价。

题目规定了从点1出发到点n,我的做法是,从起点正向跑一次spfa,可以求出所有的买入价的最小值。然后从终点反向跑一次spfa,可以求出所有卖出价的最大值。最后维护一下最大差价便是答案。

稍微想一下便能发现这个算法正确性是显然的。至少我这么认为。

建图的时候有单向边有双向边,判断一下就好了。

(我一直弄不明白判断为啥if不行swicth可以。。。)

参考代码:

  1 #include <iostream>
  2 #include <queue>
  3 #include <cstring>
  4 #include <cstdio>
  5 #define maxn 500001
  6 #define INF 0x7fffffff / 2
  7 #define debug cout << "OK" << endl;
  8 using namespace std;
  9 struct Edge{
 10     int from,to,dis;
 11 };
 12 int ball_val[maxn];
 13 int n,m,u,v,dir,w;
 14 int ans = -INF;
 15 Edge pos_edge[maxn];
 16 Edge nag_edge[maxn];
 17 int pos_head[maxn],pos_tot=0;
 18 int nag_head[maxn],nag_tot = 0;
 19 int pos_dis[maxn];
 20 int nag_dis[maxn];
 21 bool inq[maxn];
 22 int read(){
 23     int num = 0;
 24     char c;
 25     bool flag = false;
 26     while ((c = getchar()) ==   || c == \n || c == \r);
 27     if (c == -)
 28         flag = true;
 29     else
 30         num = c - 0;
 31     while (isdigit(c = getchar()))
 32         num = num * 10 + c - 0;
 33     return (flag ? -1 : 1) * num;
 34 }
 35 void pos_add_edge(int from,int to,int dis){
 36     pos_edge[++pos_tot].from=pos_head[from];
 37     pos_edge[pos_tot].to = to;
 38     pos_edge[pos_tot].dis = dis;
 39     pos_head[from] = pos_tot;
 40 }
 41 
 42 void nag_add_edge(int from,int to,int dis){
 43     nag_edge[++nag_tot].from=nag_head[from];
 44     nag_edge[nag_tot].to = to;
 45     nag_edge[nag_tot].dis = dis;
 46     nag_head[from] = nag_tot;
 47 }
 48 void pos_spfa(int s){
 49     queue<int> q;
 50     memset(inq,false,sizeof(inq));
 51     q.push(s);
 52     inq[s] = true;
 53     pos_dis[1] = ball_val[1];
 54     for (register int i=2;i<=m;i++)
 55         pos_dis[i] = INF;
 56     while (!q.empty()){
 57         int u = q.front();
 58         q.pop();
 59         inq[u] = false;
 60         for (register int i=pos_head[u];i!=0;i=pos_edge[i].from){
 61             int v = pos_edge[i].to;
 62             int w = pos_edge[i].dis;
 63             if (pos_dis[v]>w || pos_dis[v]<pos_dis[u]){
 64                 pos_dis[v] = min(w,pos_dis[u]);
 65                 if (!inq[v]){
 66                     inq[v] = true;
 67                     q.push(v);
 68                 }
 69             }
 70         }
 71     }
 72 }
 73 void nag_spfa(int s){
 74     queue<int> q;
 75     memset(inq,false,sizeof(inq));
 76     q.push(s);
 77     inq[s] = true;
 78     nag_dis[m] = ball_val[m];    
 79     for (register int i=1;i<m;i++)
 80         nag_dis[i] = -INF;
 81 
 82     while (!q.empty()){
 83         int u = q.front();
 84         q.pop();
 85         inq[u] = false;
 86         for (register int i=nag_head[u];i!=0;i=nag_edge[i].from){
 87             int v = nag_edge[i].to;
 88             int w = nag_edge[i].dis;
 89             if (nag_dis[v]<w || nag_dis[v]<nag_dis[u]){
 90                 nag_dis[v] = max(w,nag_dis[u]);
 91                 if (!inq[v]){
 92                     inq[v] = true;
 93                     q.push(v);
 94                 }
 95             }
 96         }
 97     }
 98 }
 99 
100 int main(){
101     n = read();m = read();
102     for (register int i=1;i<=n;i++)
103         ball_val[i] = read();
104     for (int i=1;i<=m;i++){
105         u =read();v = read();dir = read();
106         switch(dir){
107             case 1:
108                 pos_add_edge(u,v,ball_val[v]);
109                 nag_add_edge(v,u,ball_val[u]);
110                 break;
111             case 2:
112                 pos_add_edge(u,v,ball_val[v]);
113                 nag_add_edge(v,u,ball_val[u]);
114                 pos_add_edge(v,u,ball_val[u]);
115                 nag_add_edge(u,v,ball_val[v]);
116                 break;
117         }
118     }
119     pos_spfa(1);nag_spfa(n);
120     for (register int i=1;i<=n;i++){
121         w = nag_dis[i] - pos_dis[i];
122         ans = max(ans,w);
123     }    
124     printf("%d",ans);
125     return 0;
126 }

 

以上是关于最优贸易的主要内容,如果未能解决你的问题,请参考以下文章

[NOIP2009][LuoguP1073] 最优贸易 - Tarjan,拓扑+DP

[题解]「最短路,Noip2009」最优贸易

「CH6101」最优贸易

P1073 最优贸易

Codevs 1173 最优贸易

P1073 最优贸易