题目链接

题目

题目描述

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之间的双向道路。

输出描述

共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

输出

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。

题解

方法一

知识点:图论建模,最短路。

注意到,有三个状态,未购买、已购买未出售、已出售,互不影响。因此,建三层的分层图,同一层没有花费,但是转移到下一层时因为购买或者出售,需要边权花费。最后跑最长路即可。

时间复杂度 \(O(n+km)\)

空间复杂度 \(O(n+m)\)

方法二

知识点:最短路。

最终路线一定经过某个城市,因此考虑以某个城市为中转点,求出起点到这个城市的最小购买花费和这个城市到终点的最大出售贡献。因此,从起点跑SPFA更新每个点的最小值,在反图上从终点跑SPFA更新每个点的最大值,最后枚举每个点作为中转点即可。

时间复杂度 \(O(n+km)\)

空间复杂度 \(O(n+m)\)

代码

方法一

#include <bits/stdc++.h>
#define ll long long using namespace std; template<class T>
struct Graph {
struct edge {
int v, nxt;
T w;
};
int idx;
vector<int> h;
vector<edge> e; Graph(int n, int m) :idx(0), h(n + 1), e(m + 1) {}
void init(int n) {
idx = 0;
h.assign(n + 1, 0);
} void add(int u, int v, T w) {
e[++idx] = edge{ v,h[u],w };
h[u] = idx;
}
}; const int N = 100007 * 3, M = 500007 * 2 + N * 2;
Graph<int> g(N, M);
int n, m; bool vis[N];
int dis[N];
queue<int> q;
void SPFA(int st) {
for (int i = 1;i <= 3 * n;i++) dis[i] = -0x3f3f3f3f, vis[i] = 0;
dis[st] = 0;
q.push(1);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for (int i = g.h[u];i;i = g.e[i].nxt) {
int v = g.e[i].v, w = g.e[i].w;
if (dis[v] < dis[u] + w) {
dis[v] = dis[u] + w;
if (!vis[v]) q.push(v), vis[v] = 1;
}
}
}
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1;i <= n;i++) {
int x;
cin >> x;
g.add(i, i + n, -x);
g.add(i + n, i + 2 * n, x);
}
for (int i = 1;i <= m;i++) {
int u, v, op;
cin >> u >> v >> op;
if (op == 1) for (int i = 0;i < 3;i++) g.add(u + i * n, v + i * n, 0);
else if (op == 2) {
for (int i = 0;i < 3;i++) {
g.add(u + i * n, v + i * n, 0);
g.add(v + i * n, u + i * n, 0);
}
}
}
SPFA(1);
cout << dis[3 * n] << '\n';
return 0;
}

方法二

#include <bits/stdc++.h>
#define ll long long using namespace std; struct Graph {
struct edge {
int v, nxt;
};
int idx;
vector<int> h;
vector<edge> e; Graph(int n, int m):idx(0), h(n + 1), e(m + 1) {}
void init(int n) {
idx = 0;
h.assign(n + 1, 0);
} void add(int u, int v) {
e[++idx] = edge{ v,h[u] };
h[u] = idx;
}
}; const int N = 100007, M = 500007 * 2;
Graph g(N, M), g2(N, M);
int n, m;
int a[N]; int mi[N];
void SPFAmi(int st) {
for (int i = 1;i <= n;i++) mi[i] = 0x3f3f3f3f;
vector<bool> vis(n + 1, false);
queue<int> q; mi[st] = a[st];
vis[st] = 1;
q.push(st);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for (int i = g.h[u];i;i = g.e[i].nxt) {
int v = g.e[i].v;
if (mi[v] > min(mi[u], a[v])) {
mi[v] = min(mi[u], a[v]);
if (!vis[v]) q.push(v), vis[v] = 1;
}
}
}
} int mx[N];
void SPFAmx(int st) {
for (int i = 1;i <= n;i++) mx[i] = 0;
vector<bool> vis(n + 1, false);
queue<int> q; mx[st] = a[st];
vis[st] = 1;
q.push(st);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for (int i = g2.h[u];i;i = g2.e[i].nxt) {
int v = g2.e[i].v;
if (mx[v] < max(mx[u], a[v])) {
mx[v] = max(mx[u], a[v]);
if (!vis[v]) q.push(v), vis[v] = 1;
}
}
}
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1;i <= n;i++) cin >> a[i];
for (int i = 1;i <= m;i++) {
int u, v, op;
cin >> u >> v >> op;
if (op == 1) g.add(u, v), g2.add(v, u);
else if (op == 2) {
g.add(u, v);
g.add(v, u);
g2.add(u, v);
g2.add(v, u);
}
}
SPFAmi(1);
SPFAmx(n);
int ans = 0;
for (int i = 1;i <= n;i++)
ans = max(ans, mx[i] - mi[i]);
cout << ans << '\n';
return 0;
}

NC16611 [NOIP2009]最优贸易的更多相关文章

  1. [Luogu 1073] NOIP2009 最优贸易

    [Luogu 1073] NOIP2009 最优贸易 分层图,跑最长路. 真不是我恋旧,是我写的 Dijkstra 求不出正确的最长路,我才铤而走险写 SPFA 的- #include <alg ...

  2. [NOIP2009]最优贸易(图论)

    [NOIP2009]最优贸易 题目描述 CC 国有 \(n\) 个大城市和 \(m\) 条道路,每条道路连接这 \(n\) 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 \(m\ ...

  3. NOIP2009 最优贸易

    3. 最优贸易 (trade.pas/c/cpp) [问题描述] C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间 多只有一条道路直接相连.这 m 条道 ...

  4. 【洛谷P1073】[NOIP2009]最优贸易

    最优贸易 题目链接 看题解后感觉分层图好像非常NB巧妙 建三层n个点的图,每层图对应的边相连,权值为0 即从一个城市到另一个城市,不进行交易的收益为0 第一层的点连向第二层对应的点的边权为-w[i], ...

  5. [luogu1073 Noip2009] 最优贸易 (dp || SPFA+分层图)

    传送门 Description C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这m 条道路中有一部分为单向通行的道路,一部分 为 ...

  6. NOIP2009最优贸易[spfa变形|tarjan 缩点 DP]

    题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路 ...

  7. noip2009最优贸易

    试题描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双 ...

  8. 洛谷1073 NOIP2009 最优贸易

    题目大意 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双 ...

  9. AcWing341. 洛谷P1073, NOIP2009 最优贸易

    AcWing题目传送门 洛谷题目传送门 题目大意 \(~~~~~~\)一个投机倒把的奸商想要通过城市不太健全的贸易系统坑点钱,任意城市都可以买入或者卖出水晶球,他想尽量在便宜的城市买入,在贵的城市卖出 ...

  10. noip2009最优贸易(水晶球)

    题目:http://codevs.cn/problem/1173/ https://www.luogu.org/problemnew/show/P1073 本来考虑缩点什么的,后来发现不用. 只要记录 ...

随机推荐

  1. Navicat平替工具,一款免费开源的通用数据库工具

    前言 前段时间有小伙伴在群里提问说:因为公司不允许使用破解版的Navicat,有好用的Navicat平替工具推荐吗?今天分享一款免费开源的通用数据库工具:DBeaver. 工具介绍 DBeaver是一 ...

  2. idea 中添加查看字节码工具

    本文为博主原创,未经允许不得转载: jdk 的 bin 目录下存在 javap.exe 的工具,可通过 以下命令查看编译的字节码文件: javap -c Test.class 在 idea 中添加查看 ...

  3. 【ThreadX-FileX】Azure RTOS FileX概述

    Azure RTOS FileX嵌入式文件系统是Azure RTOS的高级工业级解决方案,适用于Microsoft FAT文件格式,专门针对深度嵌入式,实时和IoT应用程序而设计.Azure RTOS ...

  4. QT5.9移植到海思HI3520设备上运行

    前言: 在海思HI3520DV300上调试QT5.9.0有一小段时间了,这里将遇到的比较典型的问题做一个记录,以备后续查询,也可给同行一个参考.本人只使用过QT5.9.0这一个版本,如有描述错误欢迎指 ...

  5. GB18030-2022 标准学习

    GB18030-2022 标准学习 下载 https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=A1931A578FE14957104988029B08 ...

  6. [转帖]基于Fuse的用户态文件系统性能优化几点建议

    https://zhuanlan.zhihu.com/p/68085075 目前很多文件系统基于Fuse( http://fuse.sourceforge.net/ )开发,在较为深入钻研Fuse实现 ...

  7. [转帖]信创从芯开始,CPU实现国产有多难?

    https://www.eet-china.com/mp/a213516.html 数字底座的"底座"--CPU,决定信创底层逻辑的关键.CPU 是信息产业中最基础的核心部件,指令 ...

  8. [转帖]技术派-epoll和IOCP之比较

    直入正题 Epoll 用于Linux系统: IOCP 是用于 Windows: Epoll 是当事件资源满足时发出可处理通知消息: IOCP 则是当事件完成时发出完成通知消息. 从应用程序的角度来看, ...

  9. golang实现的 https 协议的四层代理和七层代理

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 四层代理 在 tcp 这一层转发很简单. http 协议是 ...

  10. .NetCore开发人员首选框架---Bridge(Abp-VNext + Vue3)

    bridge系统是基于Abp-VNext+Vue3开发的一套前后端分离的通用权限管理系统,不论是单体服务,还是微服务都可在此基础上自由扩展,此框架组合可以说是集成了.netcore在BS架构领域最前沿 ...