【luogu1073】最优贸易(队列)

题目:

我是超链接

题解:

很有意思的题目,仿佛很麻烦的样子需要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]);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值