最优贸易
原题链接: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 }
一切无法杀死我的,都将使我变得更加强大。