NC16611 [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条道路的信息(每条道路所连接的两个城市的编号以及该条道路的通行情况)。请你告诉阿龙,他最多能赚钱多少旅费。
输入描述
第一行包含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]最优贸易的更多相关文章
- [Luogu 1073] NOIP2009 最优贸易
[Luogu 1073] NOIP2009 最优贸易 分层图,跑最长路. 真不是我恋旧,是我写的 Dijkstra 求不出正确的最长路,我才铤而走险写 SPFA 的- #include <alg ...
- [NOIP2009]最优贸易(图论)
[NOIP2009]最优贸易 题目描述 CC 国有 \(n\) 个大城市和 \(m\) 条道路,每条道路连接这 \(n\) 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 \(m\ ...
- NOIP2009 最优贸易
3. 最优贸易 (trade.pas/c/cpp) [问题描述] C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间 多只有一条道路直接相连.这 m 条道 ...
- 【洛谷P1073】[NOIP2009]最优贸易
最优贸易 题目链接 看题解后感觉分层图好像非常NB巧妙 建三层n个点的图,每层图对应的边相连,权值为0 即从一个城市到另一个城市,不进行交易的收益为0 第一层的点连向第二层对应的点的边权为-w[i], ...
- [luogu1073 Noip2009] 最优贸易 (dp || SPFA+分层图)
传送门 Description C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这m 条道路中有一部分为单向通行的道路,一部分 为 ...
- NOIP2009最优贸易[spfa变形|tarjan 缩点 DP]
题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路 ...
- noip2009最优贸易
试题描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双 ...
- 洛谷1073 NOIP2009 最优贸易
题目大意 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双 ...
- AcWing341. 洛谷P1073, NOIP2009 最优贸易
AcWing题目传送门 洛谷题目传送门 题目大意 \(~~~~~~\)一个投机倒把的奸商想要通过城市不太健全的贸易系统坑点钱,任意城市都可以买入或者卖出水晶球,他想尽量在便宜的城市买入,在贵的城市卖出 ...
- noip2009最优贸易(水晶球)
题目:http://codevs.cn/problem/1173/ https://www.luogu.org/problemnew/show/P1073 本来考虑缩点什么的,后来发现不用. 只要记录 ...
随机推荐
- 使用Amber计算单点能三步走
技术背景 Amber是一个在分子动力学中非常常用的一个软件,可以用于进行分子动力学模拟计算,可以与一些软件配合进行增强采样.这里我们简单介绍一下如何使用Amber去计算一个分子构象的单点势能值,及其对 ...
- C++封装数据结构
1.概论 C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构操作. ...
- CSS - 怎么样在不同分辨率的情况下计算根元素需要的font-size的值
一般我们做页面,肯定都会有设计图,移动端页面,一般情况下,UI出图都会定宽为640px,这也是移动端的标准尺寸:但是,我们也不能排除可能有其他特殊的情况可能需要做其他大小的设计图.所以,我们可以先定一 ...
- android studio 如何把依赖导出成 jar
反编译工具 dex-tools-2.1-SNAPSHOT 第一步 用一个普通的app工程,引用所有的库,然后生成apk文件 第二步 把apk文件,改扩展名为zip,解压后,里面有几个*.dex文件,拷 ...
- GoMusic-歌单迁移工具网站 一键迁移网易云/QQ音乐歌单至 Apple/Youtube/Spotify Music
GoMusic是什么: GoMusic是一个在线歌单迁移工具网站,帮助用户一键迁移网易云/QQ音乐歌单至 Apple/Youtube/Spotify Music,直接输入歌单链接,复制查询结果,打开 ...
- Java21 + SpringBoot3整合Redis,使用Lettuce连接池,推荐连接池参数配置,封装Redis操作
目录 前言 相关技术简介 Redis 实现步骤 引入maven依赖 修改配置文件 定义Redis配置类 定义Redis服务类,封装Redis常用操作 使用Redis服务类 总结 前言 近日心血来潮想做 ...
- 【转帖】16.JVM栈帧内部结构-局部变量表
目录 1.局部变量表(Local variables) 1.局部变量表(Local variables) 1.局部变量表也称为局部变量数组或本地变量表. 2.局部变量表定义为一个数字数组,主要用于存储 ...
- [转帖]cx_Oracle.DatabaseError: ORA-28040
背景: python第三方库cx-Oracle连接Oracle数据库报错 ORA-28040 cx_Oracle.DatabaseError: ORA-28040: No matching authe ...
- docker hub arm64v8/postgres
arm64v8/postgres https://hub.docker.com/r/arm64v8/postgres By arm64v8 • Updated 4 days ago The Postg ...
- vite引入图片
vite引入图片出现的问题 -不能够页面 <template> <div> <div> <img class="imgsize" sr=& ...