题目:
题解:
很有意思的题目,仿佛很麻烦的样子需要dp,但是我们可以发现简单的队列模拟就可以过啦
f[i]表示到i点最大赚取旅费,g[i]表示到i的最小买入价格,类似SPFA遍历边,f可更新就更新f,g可更新就更新g,不管更新了哪一个,都可以加在队列里继续更新啦
代码:
#include <cstdio>
#include <queue>
#include <iostream>
#include <cstring>
#define N 100005
#define M 1000005
using namespace std;
int f[N],g[N],tot,nxt[M],point[M],v[M],w[N];
bool c[N];
//f[i]表示到i点最大赚取旅费,g[i]表示到i的最小买入价格
void addline(int x,int y){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}
int main()
{
int n,m,i;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
scanf("%d",&w[i]);
for (i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if (z==1) addline(x,y);
else addline(x,y),addline(y,x);
}
queue<int>q;
memset(c,0,sizeof(c)); c[1]=1;
memset(f,0,sizeof(f));
memset(g,0x7f,sizeof(g)); g[1]=w[1];
q.push(1);
while (!q.empty())
{
int now=q.front(); q.pop();
c[now]=false;
for (i=point[now];i;i=nxt[i])
if (f[v[i]]<max(f[now],w[v[i]]-g[now]) || g[v[i]]>min(g[now],w[v[i]]))
{
f[v[i]]=max(max(f[v[i]],f[now]),w[v[i]]-g[now]);
g[v[i]]=min(min(g[now],g[v[i]]),w[v[i]]);
if (!c[v[i]]) c[v[i]]=true,q.push(v[i]);
}
}
printf("%d",f[n]);
}