题解 P1073 【最优贸易】
安利一发自己的博客:http://www.cnblogs.com/OIerShawnZhou/
(我平常写的题解都会往博客里发,欢迎各位大佬前来拍砖)
坑点略多就是了。。有些地方必须用奇怪的写法才可以,否则绝对爆0。。。。
这题题意要求我们求出能赚取的最大差价。说到差价很好想了,肯定是卖出价-买入价=差价。
题目规定了从点1出发到点n,我的做法是,从起点正向跑一次spfa,可以求出所有的买入价的最小值。然后从终点反向跑一次spfa,可以求出所有卖出价的最大值。最后维护一下最大差价便是答案。
稍微想一下便能发现这个算法正确性是显然的。至少我这么认为。
建图的时候有单向边有双向边,判断一下就好了。
(我一直弄不明白判断为啥if不行swicth可以。。。)
参考代码:
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#define maxn 500001
#define INF 0x7fffffff / 2
#define debug cout << "OK" << endl;
using namespace std;
struct Edge{
int from,to,dis;
};
int ball_val[maxn];
int n,m,u,v,dir,w;
int ans = -INF;
Edge pos_edge[maxn];
Edge nag_edge[maxn];
int pos_head[maxn],pos_tot=0;
int nag_head[maxn],nag_tot = 0;
int pos_dis[maxn];
int nag_dis[maxn];
bool inq[maxn];
int read(){
int num = 0;
char c;
bool flag = false;
while ((c = getchar()) == ' ' || c == '\n' || c == '\r');
if (c == '-')
flag = true;
else
num = c - '0';
while (isdigit(c = getchar()))
num = num * 10 + c - '0';
return (flag ? -1 : 1) * num;
}
void pos_add_edge(int from,int to,int dis){
pos_edge[++pos_tot].from=pos_head[from];
pos_edge[pos_tot].to = to;
pos_edge[pos_tot].dis = dis;
pos_head[from] = pos_tot;
}
void nag_add_edge(int from,int to,int dis){
nag_edge[++nag_tot].from=nag_head[from];
nag_edge[nag_tot].to = to;
nag_edge[nag_tot].dis = dis;
nag_head[from] = nag_tot;
}
void pos_spfa(int s){
queue<int> q;
memset(inq,false,sizeof(inq));
q.push(s);
inq[s] = true;
pos_dis[1] = ball_val[1];
for (register int i=2;i<=m;i++)
pos_dis[i] = INF;
while (!q.empty()){
int u = q.front();
q.pop();
inq[u] = false;
for (register int i=pos_head[u];i!=0;i=pos_edge[i].from){
int v = pos_edge[i].to;
int w = pos_edge[i].dis;
if (pos_dis[v]>w || pos_dis[v]<pos_dis[u]){
pos_dis[v] = min(w,pos_dis[u]);
if (!inq[v]){
inq[v] = true;
q.push(v);
}
}
}
}
}
void nag_spfa(int s){
queue<int> q;
memset(inq,false,sizeof(inq));
q.push(s);
inq[s] = true;
nag_dis[m] = ball_val[m];
for (register int i=1;i<m;i++)
nag_dis[i] = -INF;
while (!q.empty()){
int u = q.front();
q.pop();
inq[u] = false;
for (register int i=nag_head[u];i!=0;i=nag_edge[i].from){
int v = nag_edge[i].to;
int w = nag_edge[i].dis;
if (nag_dis[v]<w || nag_dis[v]<nag_dis[u]){
nag_dis[v] = max(w,nag_dis[u]);
if (!inq[v]){
inq[v] = true;
q.push(v);
}
}
}
}
}
int main(){
n = read();m = read();
for (register int i=1;i<=n;i++)
ball_val[i] = read();
for (int i=1;i<=m;i++){
u =read();v = read();dir = read();
switch(dir){
case 1:
pos_add_edge(u,v,ball_val[v]);
nag_add_edge(v,u,ball_val[u]);
break;
case 2:
pos_add_edge(u,v,ball_val[v]);
nag_add_edge(v,u,ball_val[u]);
pos_add_edge(v,u,ball_val[u]);
nag_add_edge(u,v,ball_val[v]);
break;
}
}
pos_spfa(1);nag_spfa(n);
for (register int i=1;i<=n;i++){
w = nag_dis[i] - pos_dis[i];
ans = max(ans,w);
}
printf("%d",ans);
return 0;
}