https://daniu.luogu.org/problem/show?pid=1073#sub
显然这道题目你只要找到任何路径上的最大值,最小值就好了;
那么对于点k
我们要知道1~k里面的最小值卖入;
还要知道k~里面的最大值卖出;
那么我们可以用spfa去求;
第一遍跑出min数组后去反向图跑max数组;
这样就好了;
这道题目用缩点进行dp也可以;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define Ll long long
using namespace std;
struct cs{
int nxt,to;
}a[1000005];
int head[100005],ll;
int v[100005],ma[100005],mi[100005];
int q[2000005],l,r;
int IN[500005][3];
bool in[100005];
int n,m,x,y,z,ans;
void init(int x,int y){
a[++ll].nxt=head[x];
a[ll].to=y;
head[x]=ll;
}
void spfa(int S,int E){
l=0;r=1;
q[1]=S;mi[S]=v[S];in[S]=1;
while(r>l){
int x=q[++l];
for(int k=head[x];k;k=a[k].nxt){
if(mi[a[k].to]>min(mi[x],v[a[k].to])){
mi[a[k].to]=min(mi[x],v[a[k].to]);
if(!in[a[k].to]){
q[++r]=a[k].to;
in[a[k].to]=1;
}
}
}
in[x]=0;
}
}
void SPFA(int S){
l=0;r=1;
q[1]=S;ma[S]=v[S];in[S]=1;
while(r>l){
int x=q[++l];
for(int k=head[x];k;k=a[k].nxt){
if(ma[a[k].to]<max(ma[x],v[a[k].to])){
ma[a[k].to]=max(ma[x],v[a[k].to]);
if(!in[a[k].to]){
q[++r]=a[k].to;
in[a[k].to]=1;
}
}
}
in[x]=0;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&v[i]),mi[i]=1e9;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
IN[i][0]=x;
IN[i][1]=y;
IN[i][2]=z;
init(x,y);
if(--z)init(y,x);
}
spfa(1,n);
memset(head,0,sizeof head); ll=0;
for(int i=1;i<=m;i++){
y=IN[i][0];
x=IN[i][1];
z=IN[i][2];
init(x,y);
if(--z)init(y,x);
}
SPFA(n);
for(int i=1;i<=n;i++)ans=max(ans,ma[i]-mi[i]);
printf("%d",ans);
}