题意
找一条路径上的点p,q,先经过点p,再经过点q,使q-p最大,求这个最大值。
1≤n≤100000,1≤m≤500000
分析
其实图论模型和dp模型很类似,一个点到下一个点就是一个状态到下一个状态
我们考虑正反两次跑一下这个图,正着跑算出b[i]表示到当前点为止访问过的点的最小价值。
反向加边,算出s[i]表示到当前点为止访问过的点的最大价值。而这个只需要在松弛最短路的时候改一句话就行了。
最后的答案就是max{s[i]-b[i]}
MD写迪杰WA半天 向spfa屈服
代码
#include<bits/stdc++.h> using namespace std; #define N 200020 int n,m,cnt,cot,ans; int w[N],b[N],s[N],vis[N],first[N],head[N]; struct email { int u,v; int nxt; }e[N*5],g[N*5]; queue<int>q; inline void add1(int u,int v) { e[++cnt].nxt=first[u];first[u]=cnt; e[cnt].u=u;e[cnt].v=v; } inline void add2(int u,int v) { g[++cot].nxt=head[u];head[u]=cot; g[cot].u=u;g[cot].v=v; } void spfa() { memset(b,0x3f,sizeof(b)); b[1]=w[1]; q.push(1);vis[1]=1; while(!q.empty()) { int u=q.front();q.pop();vis[u]=0; for(int i=first[u];i;i=e[i].nxt) { int v=e[i].v; if(b[v]>b[u]) { b[v]=min(w[v],b[u]); if(!vis[v])q.push(v),vis[v]=1; } } } memset(vis,0,sizeof(vis)); s[n]=w[n]; q.push(n);vis[n]=1; while(!q.empty()) { int u=q.front();q.pop();vis[u]=0; for(int i=head[u];i;i=g[i].nxt) { int v=g[i].v; if(s[v]<s[u]) { s[v]=max(w[v],s[u]); if(!vis[v])q.push(v),vis[v]=1; } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&w[i]); for(int i=1;i<=m;i++) { int u,v,c; scanf("%d%d%d",&u,&v,&c); if(c==1)add1(u,v),add2(v,u); else { add1(u,v);add1(v,u); add2(u,v);add2(v,u); } } spfa(); for(int i=1;i<=n;i++)ans=max(ans,s[i]-b[i]); printf("%d ",ans); return 0; }