反向建图+dijkstra
切一道老题水水。。。
题目的意思是让我们找到两个点x,y,使得差值最大。
所以我们先在正向图跑dijkstra,用d数组表示从起点到i点的最少价值,所以可以用d[i]=min(w[i], d[j])更新d值
再用f数组表示从该点到终点的最大价值,这次我们在反向图从n点开始跑dijkstra,这在反向图表示从n到某点的最短路(在正向图即该点到终点的最短路),更新方法与上述类似。
最后遍历每个点去f[i]-d[i]的最大值即可。
我开始想用f/d直接更新,d[i]=min(d[i], d[j])。。但是这样有时候得不到正确答案,因为我太弱了,只能想到当图不联通的时候这样是错误的。。。
因为当某个点与起点或者终点不联通时,按照d[i]=min(d[i], d[j])的方法更新,需要一开始就给所有点的d/f数组附上w的初值,这样以来就变成了d[i]=f[i],最后得出的答案一定是0,但是其实我们在联通的那一部分已经有卖出差价了
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
int X = 0, w = 0; char ch = 0;
while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
return w ? -X : X;
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C yql){
A ans = 1;
for(; p; p >>= 1, x = 1LL * x * x % yql)if(p & 1)ans = 1LL * x * ans % yql;
return ans;
}
const int N = 100000;
int n, m, cnt1, cnt2, head1[N], head2[N], w[N], d[N], f[N];
bool vis[N];
struct Edge{
int v, next;
}edge1[5*N], edge2[5*N];
void addEdge1(int a, int b){
edge1[cnt1].v = b;
edge1[cnt1].next = head1[a];
head1[a] = cnt1 ++;
}
void addEdge2(int a, int b){
edge2[cnt2].v = b;
edge2[cnt2].next = head2[a];
head2[a] = cnt2 ++;
}
void dijkstra_to(){
memset(d, INF, sizeof d);
memset(vis, 0, sizeof vis);
//for(int i = 1; i <= n; i ++) d[i] = w[i];
priority_queue<pair<int, int>, vector<pair<int, int>>, less<pair<int, int>>> pq;
d[1] = w[1];
pq.push(make_pair(d[1], 1));
while(!pq.empty()){
int s = pq.top().second, dis = pq.top().first; pq.pop();
if(vis[s]) continue;
vis[s] = true;
for(int i = head1[s]; i != -1; i = edge1[i].next){
int u = edge1[i].v;
d[u] = min(dis, w[u]);
pq.push(make_pair(d[u], u));
}
}
}
void dijkstra_from(){
memset(f, 0, sizeof f);
memset(vis, 0, sizeof vis);
//for(int i = 1; i <= n; i ++) f[i] = w[i];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
f[n] = w[n];
pq.push(make_pair(w[n], n));
while(!pq.empty()){
int s = pq.top().second, dis = pq.top().first; pq.pop();
if(vis[s]) continue;
vis[s] = true;
for(int i = head2[s]; i != -1; i = edge2[i].next){
int u = edge2[i].v;
f[u] = max(dis, w[u]);
pq.push(make_pair(f[u], u));
}
}
}
int main(){
memset(head1, -1, sizeof head1);
memset(head2, -1, sizeof head2);
n = read(), m = read();
for(int i = 1; i <= n; i ++) w[i] = read();
for(int i = 0; i < m; i ++){
int a = read(), b = read(), c = read();
if(c == 1) addEdge1(a, b), addEdge2(b, a);
else if(c == 2) addEdge1(a, b), addEdge1(b, a), addEdge2(a, b), addEdge2(b, a);
}
dijkstra_to(), dijkstra_from();
int ans = 0;
for(int i = 1; i <= n; i ++)
ans = max(ans, f[i] - d[i]);
printf("%d
", ans);
return 0;
}