题目链接
感觉这道题只要知道spfa算法可以枚举沿途最大点和最小点,正向和反向建图,两遍spfa即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 500010
ll n,m,cnt1,cnt2,ans;ll head1[maxn],head2[maxn];
ll dis1[maxn],dis2[maxn];ll vis1[maxn],vis2[maxn];
ll val[maxn];
ll aa,bb,opt;
struct node{
ll y,next;
}ed1[maxn],ed2[maxn];
queue<int>q1;queue<int>q2;
void add1(ll xx,ll yy){//正向建图
++cnt1;
ed1[cnt1].y=yy;
ed1[cnt1].next=head1[xx];
head1[xx]=cnt1;
}
void add2(ll xx,ll yy){//反向建图
++cnt2;
ed2[cnt2].y=yy;
ed2[cnt2].next=head2[xx];
head2[xx]=cnt2;
}
void spfa1(){//找的是最小的
memset(dis1,0x3f,sizeof(dis1));
memset(vis1,0,sizeof(vis1));
vis1[1]=1;q1.push(1);dis1[1]=val[1];
while(!q1.empty()){
ll x=q1.front();q1.pop();
vis1[x]=0;
for(int i=head1[x];i;i=ed1[i].next){
ll vv=ed1[i].y;
if(dis1[x]<dis1[vv]){
dis1[vv]=min(dis1[x],val[vv]);
if(!vis1[vv]){
vis1[vv]=1;q1.push(vv);
}
}
}
}
}
void spfa2(){//找的是最大的
memset(dis2,0,sizeof(dis2));
memset(vis2,0,sizeof(vis2));
vis2[n]=1;q2.push(n);dis2[n]=val[n];
while(!q2.empty()){
int x=q2.front();q2.pop();
vis2[x]=0;
for(int i=head2[x];i;i=ed2[i].next){
ll vv=ed2[i].y;
if(dis2[x]>dis2[vv]){
dis2[vv]=max(dis2[x],val[vv]);
if(!vis2[vv]){
vis2[vv]=1;q2.push(vv);
}
}
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;++i)cin>>val[i];
// for(int i=1;i<=n;++i){dis1[i]=dis2[i]=val[i];}
for(int i=1;i<=m;++i){
cin>>aa>>bb>>opt;
add1(aa,bb);add2(bb,aa);
if(opt==2)add1(bb,aa),add2(aa,bb);
}
spfa1();spfa2();
for(int i=1;i<=n;++i){
// printf("%lld %lld\n",dis1[i],dis2[i]);
ans=max(ans,dis2[i]-dis1[i]);
}
printf("%lld\n",ans);
return 0;
}