[题目链接]
https://www.luogu.org/problemnew/show/P1073
[算法]
首先,我们知道,如果进行贸易,一定是选择某个节点到终点路径上商品价格的最大值 - 起点到该节点路径上商品价格的最小值
那么算法就很明确了 : 建一张正向图和反向图,分别用spfa求出起点/终点到该节点路径上的商品价格最小/最大值,最后枚举每个节点更新答案即可
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 #define MAXM 500010 int i,n,m,x,y,z,tot,ans; int a[MAXN],f[MAXN],g[MAXN],head[MAXN],rhead[MAXN]; struct edge { int to,nxt; } e[MAXM << 2]; inline void addedge(int u,int v) { tot++; e[tot] = (edge){v,head[u]}; head[u] = tot; } inline void addredge(int u,int v) { tot++; e[tot] = (edge){v,rhead[u]}; rhead[u] = tot; } /* Graph A, find minimum price */ inline void spfa1() { int i,v,cur; queue< int > q; memset(f,0x3f,sizeof(f)); f[1] = a[1]; q.push(1); while (!q.empty()) { cur = q.front(); q.pop(); for (i = head[cur]; i; i = e[i].nxt) { v = e[i].to; if (min(f[cur],a[v]) < f[v]) { f[v] = min(f[cur],a[v]); q.push(v); } } } } /* Graph B,find maximum price */ inline void spfa2() { int i,v,cur; queue< int > q; memset(g,0,sizeof(g)); g[n] = a[n]; q.push(n); while (!q.empty()) { cur = q.front(); q.pop(); for (i = rhead[cur]; i; i = e[i].nxt) { v = e[i].to; if (max(g[cur],a[v]) > g[v]) { g[v] = max(g[cur],a[v]); q.push(v); } } } } int main() { scanf("%d%d",&n,&m); for (i = 1; i <= n; i++) scanf("%d",&a[i]); for (i = 1; i <= m; i++) { scanf("%d%d%d",&x,&y,&z); if (z == 1) { addedge(x,y); addredge(y,x); } else { addedge(x,y); addedge(y,x); addredge(x,y); addredge(y,x); } } spfa1(); spfa2(); for (i = 1; i <= n; i++) ans = max(ans,g[i] - f[i]); printf("%d\n",ans); return 0; }
原文:https://www.cnblogs.com/evenbao/p/9372720.html