NOIP2009最优贸易
题目描述
C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市。任意两个 城市之间最多只有一条道路直接相连。这m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路,双向通行的道路在统计条数时也计为1 条。 C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价 格不一定相同。但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。 商人阿龙来到 C 国旅游。当他得知同一种商品在不同城市的价格可能会不同这一信息 之后,便决定在旅游的同时,利用商品在不同城市中的差价赚回一点旅费。设C 国n 个城 市的标号从1~ n,阿龙决定从1 号城市出发,并最终在n 号城市结束自己的旅行。在旅游的 过程中,任何城市可以重复经过多次,但不要求经过所有n 个城市。阿龙通过这样的贸易方 式赚取旅费:他会选择一个经过的城市买入他最喜欢的商品——水晶球,并在之后经过的另 一个城市卖出这个水晶球,用赚取的差价当做旅费。由于阿龙主要是来C 国旅游,他决定 这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。 假设 C 国有5 个大城市,城市的编号和道路连接情况如下图,单向箭头表示这条道路 为单向通行,双向箭头表示这条道路为双向通行。 假设 1~n 号城市的水晶球价格分别为4,3,5,6,1。 阿龙可以选择如下一条线路:1->2->3->5,并在2 号城市以3 的价格买入水晶球,在3 号城市以5 的价格卖出水晶球,赚取的旅费数为2。 阿龙也可以选择如下一条线路 1->4->5->4->5,并在第1 次到达5 号城市时以1 的价格 买入水晶球,在第2 次到达4 号城市时以6 的价格卖出水晶球,赚取的旅费数为5。 现在给出 n 个城市的水晶球价格,m 条道路的信息(每条道路所连接的两个城市的编号 以及该条道路的通行情况)。请你告诉阿龙,他最多能赚取多少旅费。
solution
跑两遍spfa。
第一遍记录从起点到点i的路径上的最小值
第二遍反向建图,spfa处理出到终点的最大值
由于好久没写代码了,反向建图时copy的正向的,忘改了,调了半个小时。。。
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 #define MAXM 500010 inline int read() { int f=1,x=0; char ch; do { ch=getchar(); if(ch=='-') f=-1; }while(ch<'0'||ch>'9'); do { x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); }while(ch>='0'&&ch<='9'); return f*x; } struct node { int to; int next; int val; }; int head[MAXN],head1[MAXN],cnt1=0,cnt2=0; int n,m; node g1[MAXM*2],g2[MAXM*2]; int v[MAXN]; int dis[MAXN],dis2[MAXN]; bool inq[MAXN]; inline void addedge(int a,int b,int v) { ++cnt1;g1[cnt1].to=b;g1[cnt1].next=head[a];head[a]=cnt1;g1[cnt1].val=v; ++cnt2;g2[cnt2].to=a;g2[cnt2].next=head1[b];head1[b]=cnt2;g2[cnt2].val=v; } inline void spfa() { memset(inq,false,sizeof(inq)); queue<int>q; dis[1]=v[1]; inq[1]=1; q.push(1); while(q.size()) { int u=q.front(); inq[u]=0; q.pop(); for(int i=head[u];i;i=g1[i].next) { int v=g1[i].to; if(dis[v]>min(dis[u],g1[i].val)) { dis[v]=min(dis[u],g1[i].val); if(!inq[v]) q.push(v),inq[v]=1; } } } } inline void spfa2() { memset(inq,false,sizeof(inq)); queue<int>q; dis2[n]=v[n]; inq[n]=1; q.push(n); while(q.size()) { int u=q.front(); inq[u]=0; q.pop(); for(int i=head1[u];i;i=g2[i].next) { int v=g2[i].to; if(dis2[v]<max(dis2[u],g2[i].val)) { dis2[v]=max(dis2[u],g2[i].val); if(!inq[v]) q.push(v),inq[v]=1; } } } } int main() { n=read();m=read(); for(int i=1;i<=n;i++) v[i]=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(),z=read(); if(z==1) addedge(x,y,v[y]); if(z==2) addedge(x,y,v[y]),addedge(y,x,v[x]); } memset(dis,37,sizeof(dis)); memset(dis2,-37,sizeof(dis2)); spfa(); spfa2(); int ans=0; for(int i=1;i<=n;i++) ans=max(ans,dis2[i]-dis[i]); cout<<ans<<endl; }