luogu P1073 最优贸易
来源:互联网 发布:大平面铣削编程 编辑:程序博客网 时间:2024/05/17 23:50
题目描述
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 条道路的信息(每条道路所连接的两个城市的编号以及该条道路的通行情况)。请你告诉阿龙,他最多能赚取多少旅费。
输入输出格式
输入格式:
第一行包含 2 个正整数 n 和 m,中间用一个空格隔开,分别表示城市的数目和道路的数目。
第二行 n 个正整数,每两个整数之间用一个空格隔开,按标号顺序分别表示这 n 个城市的商品价格。
接下来 m 行,每行有 3 个正整数,x,y,z,每两个整数之间用一个空格隔开。如果 z=1,表示这条道路是城市 x 到城市 y 之间的单向道路;如果 z=2,表示这条道路为城市 x 和城市y 之间的双向道路。
输出格式:
输出文件 trade.out 共 1 行,包含 1 个整数,表示最多能赚取的旅费。如果没有进行贸易,则输出 0。
输入输出样例
输入样例#1:
5 5
4 3 5 6 1
1 2 1
1 4 1
2 3 2
3 5 1
4 5 2
输出样例#1:
5
说明
【数据范围】
输入数据保证 1 号城市可以到达 n 号城市。
对于 10%的数据,1≤n≤6。
对于 30%的数据,1≤n≤100。
对于 50%的数据,不存在一条旅游路线,可以从一个城市出发,再回到这个城市。
对于 100%的数据,1≤n≤100000,1≤m≤500000,1≤x,y≤n,1≤z≤2,1≤各城市
水晶球价格≤100。
NOIP 2009 提高组 第三题
题目很长,总结一下,就是说我们有一张图,图中有一些有向边,有一些无向边,然后每个点有点权,要求我们找一条由1到n的路径,使得这条路径上的点A和点B的点权差值最大,且要求保证节点A在节点B之前遍历到,且节点B的点权大于节点A的点权;
乍一看没什么思路,但是仔细分析,发现我们要找一条1到n的路径上的两个最值点,而且要使点权大的点后遍历到,那么,第一个想法就是搜索;
搜索: 首先,我们从1开始遍历的时候要更新最小值和最大值,又因为有先后这个条件,我们还需要记录遍历到的时间,然后,再次遍历去处理,但是显然这样子极难实现,就算实现了,也会有很多bug,就算没有bug,也肯定会TLE,所以,我们要另寻他路;
还是根据遍历要求先后这个条件,我们可以根据显然定理,经分析发现,点权小的那个点,一定是靠近1的,而同理,点权大的点靠近n;
由以上分析可得,这个题我们需要正反两次搜索,一次求最大值,一次求最小值,而且由于是搜索,而且没有太多限制(遍历先后这个限制我们拆成了两个搜索,等价于没有了这个限制),所以我们可以选择用spfa来解决这道题;
正解:
我们从n开始,做一次spfa,求到达每个点的最大值,并且标记达到过哪些点,这样我们就可以知道那些点可以到达n,然后从1开始,做一次spfa,更新最小值时,如果这个点可以达到n,我们就更新答案ans;做完两次spfa后,输出ans即可;
至于代码:
#include<iostream>#include<cstdio>#include<queue>#define II int#define R register#define I 1000010using namespace std;struct node { II to,up;}aa[I],aa_f[I];queue <II> Q;II inq[I],head[I],head_f[I],out_f[I],out[I],boby[I],mi[I],ma[I],has[I];II n,m,_tot,_tot_f,ans;void add(R II x,R II y){ out[x]++; aa[++_tot].to=y; aa[_tot].up=head[x]; head[x]=_tot; //正着存图; out_f[y]++; aa_f[++_tot_f].to=x; aa_f[_tot_f].up=head_f[y]; head_f[y]=_tot_f; //倒着再存一遍图;}void spfa(){ Q.push(n); inq[n]=1; while (!Q.empty()) { R II x=Q.front(); Q.pop(); inq[x]=0; for(R II i=head_f[x];i;i=aa_f[i].up) { R II go=aa_f[i].to; if(out_f[x]&&!inq[go]) inq[go]=1,Q.push(go),out_f[x]--,has[x]=1; //每个点所连的边遍历一次就好; if(ma[go]<ma[x]&&out_f[x]) ma[go]=ma[x]; //更新最大值; } }}void spfa_1(){ for(R II i=1;i<=n;i++) inq[i]=0; Q.push(1); inq[1]=1; while (!Q.empty()) { R II x=Q.front(); Q.pop(); inq[x]=0; for(R II i=head[x];i;i=aa[i].up) { R II go=aa[i].to; if(mi[go]>mi[x]) mi[go]=mi[x]; //更新最小值; if(out[x]&&!inq[go]) inq[go]=1,Q.push(go),out[x]--; //同理,每个点连的边只需要走一次就好; if(has[go]) ans=max(ans,ma[go]-mi[go]); //如果这个点可以到达n,更新答案; } } printf("%d\n",ans);}int main(){ scanf("%d%d",&n,&m); for(R II i=1;i<=n;i++) scanf("%d",&boby[i]),mi[i]=boby[i],ma[i]=boby[i]; //最开始每个点的最大值、最小值都是自己; for(R II i=1;i<=m;i++) { R II x,y,z; scanf("%d%d%d",&x,&y,&z); if(z==1) add(x,y); //单向边; else add(x,y),add(y,x); //双向边; } spfa(); //倒着从n做spfa; spfa_1(); //正着从1做spfa; return 0;}
by pretend-fal;
END;
- luogu P1073 最优贸易
- 洛谷 P1073 最优贸易
- 洛谷 P1073 最优贸易
- 洛谷 P1073 最优贸易
- 洛谷 P1073 最优贸易
- P1073 最优贸易
- P1073最优贸易
- 洛谷 P1073 最优贸易
- 洛谷P1073&NOIP2009 最优贸易
- 【 洛谷P1073 】【NOIP2009】最优贸易
- spfa-洛谷P1073 最优贸易
- 洛谷 P1073 [NOIP2009 T3] 最优贸易
- P1073 最优贸易 NOIP 2009 最短路
- 【NOIP2009】洛谷P1073 最优贸易(SPFA + 反向建图)
- 最优贸易
- 最优贸易
- 最优贸易
- 最优贸易
- Unity3D之UI按键绑定事件(五)
- 浅谈项目系统架构分层
- 排列组合
- Spring boot war部署
- CAD 学习笔记 Mac
- luogu P1073 最优贸易
- warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
- 文件下载
- MySQL 按照时间查询
- SpringBoot 配置分析(一)
- Python 函数参数引用(传值/传址)/copy/deepcopy
- 指针经典例题
- 请问什么是Servlet上下文?
- 17/8/2学习笔记03