题面要求的是一个差值,即走过一条路径能找到的路径上最大值-最小值。
那么相当于跑一遍最长路和一遍最短路,当然不是概念上的最长路最短路,这里把dis[v]的松弛改成用路径上传递来的最大/最小值维护,而不是上一个点传来的dis[u]+w(u,v)。
同时这样的松弛中还要和这个点本身的权值作比较。
跑最长/最短路满足能走到终点这一题意,同时保证之前的最大值/最小值能传递到走到的这个点。
跑完两次松弛最长路/最短路以后,枚举每个点存下的最大值-最小值,更新最终ans。
代码如下(当时码风很丑甚至开了O2,但是思路是对的):
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=100001,M=1000001; int ver[M],head[N],Next[M]; int verx[M],headx[N],Nextx[M]; int price[N]; int n,m,tot,tott,ans; int ff[N],dd[N]; void add(int x,int y){ ver[++tot]=y; Next[tot]=head[x]; head[x]=tot; } void ad(int x,int y){ verx[++tott]=y; Nextx[tott]=headx[x]; headx[x]=tott; } priority_queue<pair<int,int> >q; int shot(){ memset(ff,0x3f,sizeof(ff)); ff[1]=price[1]; q.push(make_pair(ff[1],1)); while(q.size() ){ int y=q.top() .second; q.pop() ; for(int i=head[y];i;i=Next[i]){ if(ff[ver[i]]>min(price[ver[i]],ff[y])){ ff[ver[i]]=min(price[ver[i]],ff[y]); q.push(make_pair(-ff[ver[i]],ver[i])); } } } } int lng(){ memset(dd,0,sizeof(dd)); dd[n]=price[n]; q.push(make_pair(dd[n],n)); while(q.size() ){ int y=q.top() .second; q.pop() ; for(int i=headx[y];i;i=Nextx[i]){ if(dd[verx[i]]<max(price[verx[i]],dd[y])){ dd[verx[i]]=max(price[verx[i]],dd[y]); q.push(make_pair(dd[verx[i]],verx[i])); } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&price[i]); } for(int i=1,x,y,z;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); if(z==1){ add(x,y); ad(y,x); } else { add(x,y); add(y,x); ad(x,y); ad(y,x); } } shot(); lng(); for(int i=1;i<=n;i++){ ans=max(dd[i]-ff[i],ans); } printf("%d",ans); return 0; }