解题思路
首先可以将无向图视作有向图,然后建立一个反图,之后正着跑一遍最短路存到dis里,dis[x]表示1-x的路径中权值最小节点的权值,反着跑一遍最长路,dis_[x]表示x-n中权值最大的节点的权值,之后用dis_[x]-dis[x]来更新答案。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 100005,MAXM = 500005;
struct Edge{
int nxt,to;
}edge[MAXM],edge_s[MAXM];
int head_s[MAXN],cnt_s,dis_s[MAXN],ans;
int n,m,cnt,head[MAXN],dis[MAXN],val[MAXN];
bool vis[MAXN],vis_s[MAXN];
queue<int> q,Q;
inline void add(int bg,int ed){
edge[++cnt].to=ed;
edge[cnt].nxt=head[bg];
head[bg]=cnt;
}
inline void add_s(int bg,int ed){
edge_s[++cnt_s].to=ed;
edge_s[cnt_s].nxt=head_s[bg];
head_s[bg]=cnt_s;
}
inline void spfa(){
memset(dis,0x3f,sizeof(dis));
vis[1]=1;q.push(1);dis[1]=val[1];
while(!q.empty()){
int x=q.front();q.pop();
vis[x]=0;
for(int i=head[x];i;i=edge[i].nxt){
int u=edge[i].to;
if(dis[u]>min(val[u],dis[x])){
dis[u]=min(val[u],dis[x]);
if(!vis[u]){
vis[u]=1;
q.push(u);
}
}
}
}
// for(register int i=1;i<=n;i++)
// cout<<dis[i]<<endl;
}
inline void spfa_s(){
memset(dis_s,-1,sizeof(dis_s));
vis_s[n]=1;
dis_s[n]=val[n];
Q.push(n);
while(!Q.empty()){
int x=Q.front();Q.pop();
vis_s[x]=1;
for(int i=head_s[x];i;i=edge_s[i].nxt){
int u=edge_s[i].to;
if(dis_s[u]<max(dis_s[x],val[u])){
dis_s[u]=max(dis_s[x],val[u]);
if(!vis_s[u]){
vis_s[u]=1;
Q.push(u);
}
}
}
}
// for(register int i=1;i<=n;i++)
// cout<<dis_s[i]<<endl;
}
int main(){
scanf("%d%d",&n,&m);
for(register int i=1;i<=n;i++) scanf("%d",&val[i]);
for(register int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(z==1){
add(x,y);
add_s(y,x);
}
else{
add(x,y);add(y,x);
add_s(x,y);add_s(y,x);
}
}spfa();spfa_s();
for(register int i=1;i<=n;i++)
ans=max(dis_s[i]-dis[i],ans);
printf("%d",ans);
return 0;
}