看网上有很多很麻烦的做法,这里提供一个最简单的
设
d
i
s
i
dis_i
disi 表示
1
1
1 到
i
i
i 的所有路径上的最小点权(水晶球价格),
d
i
s
t
i
dist_i
disti 表示
i
i
i 到
n
n
n 的所有路径上的最大点权。
那么,最后的答案就是
max
i
=
1
n
{
d
i
s
t
i
−
d
i
s
i
}
\max\limits_{i=1}^n \{dist_i-dis_i\}
i=1maxn{disti−disi}
因为每个点可以经过多次,用的是SPFA
#include<cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int Maxn=100000+10,inf=0x3f3f3f3f;
vector <int> e[Maxn],g[Maxn];
int a[Maxn],dis[Maxn],dist[Maxn];
int n,m,ans;
bool vis[Maxn];
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
void spfa1()
{
fill(dis+1,dis+1+n,inf);
queue <int> q;
vis[1]=1,dis[1]=a[1];
q.push(1);
while(q.size())
{
int x=q.front();
q.pop();
vis[x]=0;
for(int i=0;i<e[x].size();++i)
{
int y=e[x][i];
if(dis[y]>min(dis[x],a[y]))
{
dis[y]=min(dis[x],a[y]);
if(!vis[y])vis[y]=1,q.push(y);
}
}
}
}
void spfa2()
{
fill(dist+1,dist+1+n,-inf);
queue <int> q;
vis[n]=1,dist[n]=a[n];
q.push(n);
while(q.size())
{
int x=q.front();
q.pop();
vis[x]=0;
for(int i=0;i<g[x].size();++i)
{
int y=g[x][i];
if(dist[y]<max(dist[x],a[y]))
{
dist[y]=max(dist[x],a[y]);
if(!vis[y])vis[y]=1,q.push(y);
}
}
}
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;++i)
a[i]=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read(),opt=read();
e[x].push_back(y);
g[y].push_back(x);
if(opt==2)
{
e[y].push_back(x);
g[x].push_back(y);
}
}
spfa1();
spfa2();
for(int i=1;i<=n;++i)
ans=max(ans,dist[i]-dis[i]);
printf("%d\n",ans);
return 0;
}