AcWing341 CH6101 最优贸易
Posted Luowaterbi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing341 CH6101 最优贸易相关的知识,希望对你有一定的参考价值。
题意:
一个有向图,一个物品在每个点有不同的价值,从起点到终点的路径上,可以先在某个点买一个,再在某一个点卖掉,问能赚到最多的钱是多少。
题解:
一开始以为是求路径上最大点权之差,但是发现必须先买才能在卖,顺序不能反。
这样一个问题,我们将其分割成两个单调的子问题,从起点到一点的路径上,能用最少多少钱买到物品;从一点到终点,能用最多多少钱卖掉物品。在第一个问题里把物品价值取相反数,在第二个问题里建一个反图,就成了两个相同的问题。遍历每个点,用最多的钱减去最少的钱就是答案。
注意不能反过来。不能说从起点到一点的路径上,能用最多多少钱卖掉物品;从一点到终点,能用最少多少钱买到物品。对于一个点,要保证买东西的点一定在起点到该点之间,卖东西的点一定在该点到终点之间。如果反过来,那就可能导致”先卖再买“的情况。
这样一个图上前缀最大的问题,跟最短路差不多,只是将更新的 d i s [ x ] = d i s [ y ] + w dis[x]=dis[y]+w dis[x]=dis[y]+w换成了 d i s [ x ] = m a x ( d i s [ y ] , p r i c e [ x ] ) dis[x]=max(dis[y],price[x]) dis[x]=max(dis[y],price[x])。所以可以用spfa来解决。但是注意,不能保证一个点只更新一次。因为我们更新的过程不是单调的,由于 p r i c e [ x ] price[x] price[x]的存在,后面的 d i s [ x ] dis[x] dis[x]不一定大于前面 d i s [ y ] dis[y] dis[y]。所以我个人认为不能用Dijstra,但是书上说可以。
经过一些巧妙的设计,可以显著减少代码量。
AC代码:
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define lep(i,a,b) for(int i=(a);i>=(b);i--)
#define lepp(i,a,b) for(int i=(a);i>(b);i--)
#define sci(x) scanf("%d",&(x))
#define scl(x) scanf("%lld",&(x))
#define scs(x) scanf("%s",(x))
#define pri(x) printf("%d\\n",(x))
#define prl(x) printf("%lld\\n",(x))
#define prs(x) printf("%s\\n",(x))
#define pii pair<int,int>
#define pll pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define All(x) x.begin(),x.end()
#define ms(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define INFF 0x3f3f3f3f3f3f3f3f
#define multi int T;scanf("%d",&T);while(T--)
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+5;
const int mod=1e9+7;
const db eps=1e-6;
const db pi=acos(-1.0);
int n,m,p[N],q[N],dis[N],vis[N];
vector<int>tr1[N],tr2[N];
void dij(vector<int>tr[N],int s,int pq[N])
priority_queue<pii>d;
d.push(pq[s],s);
rep(i,1,n) dis[i]=-INF;
dis[s]=pq[s];
while(d.size())
pii tmp=d.top();
d.pop();
// if(vis[tmp.first]) continue;
// vis[tmp.first]=1;
for(auto v:tr[tmp.second])
int cur=max(tmp.first,pq[v]);
if(cur>dis[v])
dis[v]=cur;
d.push(cur,v);
rep(i,1,n) pq[i]=dis[i];
int main()
#ifndef ONLINE_JUDGE
freopen("D:\\\\work\\\\data.in","r",stdin);
#endif
cin>>n>>m;
rep(i,1,n)
cin>>q[i];
p[i]=-q[i];
rep(i,1,m)
int u,v,w;
cin>>u>>v>>w;
tr1[u].push_back(v);
tr2[v].push_back(u);
if(w==2)
tr1[v].push_back(u);
tr2[u].push_back(v);
dij(tr1,1,p);
dij(tr2,n,q);
int ans=0;
rep(i,1,n) ans=max(ans,q[i]+p[i]);
cout<<ans<<endl;
以上是关于AcWing341 CH6101 最优贸易的主要内容,如果未能解决你的问题,请参考以下文章