解题思路:
对于每个地点,找到前面最小的,找到后面最大的。然后遍历每个点,找出差值最大。
#include<bits/stdc++.h>
#include<queue>
using namespace std;
const int maxn=3e5+177;
int n,m;
struct Node{
int next;
int to;
}edge[maxn],edge1[maxn];
int p[maxn];
int head[maxn],head1[maxn];
int dis1[maxn],vis[maxn];
int dis2[maxn];
int num_edge,num_edge1;
void add(int u,int v){
edge[++num_edge].next=head[u];
edge[num_edge].to=v;
head[u]=num_edge;
}
void add1(int u,int v){
edge1[++num_edge1].next=head1[u];
edge1[num_edge1].to=v;
head1[u]=num_edge1;
}
void init1(){
memset(head,0,sizeof(head));
memset(head1,0,sizeof(head1));
num_edge=0;
num_edge1=0;
}
void spfa1(int x){
memset(dis1,0x3f,sizeof(dis1));
memset(vis,0,sizeof(vis));
dis1[x]=p[x];
vis[x]=1;
queue<int >qu;
qu.push(x);
while(!qu.empty()){
int now=qu.front();
qu.pop();
for(int i=head[now];i;i=edge[i].next){
int y=edge[i].to;
if(dis1[y]>min(dis1[now],p[y])){
dis1[y]=min(dis1[now],p[y]);
// printf("%d @@ %d |||||| %d %d\n",dis1[y],y,dis1[now],now);
if(!vis[y]){
qu.push(y);
vis[y]=1;
}
}
}
}
}
void spfa2(int x){
memset(vis,0,sizeof(vis));
memset(dis2,0,sizeof(dis2));
dis2[x]=p[x];
vis[x]=1;
queue<int >que;
que.push(x);
while(!que.empty()){
int now=que.front();
que.pop();
for(int i=head1[now];i;i=edge1[i].next){
int y=edge1[i].to;
if(dis2[y]<max(p[y],dis2[now])){
dis2[y]=max(p[y],dis2[now]);
// printf("%d -- %d \n",dis2[y],y);
if(!vis[y]){
que.push(y);
vis[y]=1;
}
}
}
}
}
int main(){
cin>>n>>m;
init1();
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
}
int u,v,z;
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&z);
if(z==1){
add(u,v);
add1(v,u);
}else{
add(u,v);
add(v,u);
add1(u,v);
add1(v,u);
}
}
spfa1(1);
spfa2(n);
int ans=-1;
for(int i=1;i<=n;i++){
// printf("%d !!! %d \n",dis2[i],dis1[i]);
ans=max(ans,dis2[i]-dis1[i]);
}
printf("%d\n",ans);
}