题目链接

题目

题目描述

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. Elasticsearch 索引与文档的常用操作总结二:复杂条件查询

    本文为博主原创,未经允许不得转载: 1.  查询所有:match_all GET /es_db/_doc/_search { "query":{ "match_all&q ...

  2. Redis 哨兵模式高可用

    本文为博主原创,未经允许不得转载: 目录: 1. 哨兵 Sentinel 介绍 2. 哨兵架构特点及工作原理 3. redis哨兵架构搭建步骤 4. 哨兵数据丢失 5. spring boot 整合  ...

  3. React技巧之设置input值

    原文链接:https://bobbyhadz.com/blog/react-set-input-value-on-button-click 作者:Borislav Hadzhiev 正文从这开始~ 总 ...

  4. 问题--C中结构体想要嵌套一个该结构体指针,但是系统无法识别该类型

    代码如下: typedef struct_Person{ char name[64]; int age; //Person* person; //这里会出现一个问题,由于Person是在末尾定义的,那 ...

  5. Go-强制类型转换-T(x)

    类型转换 T(x) 具有相同的底层类型 数字类型之间可以互相转换(int系 uint系 float系),较大数转换成较小数会损失精度 字符串与切片之间的转换 string <==> []r ...

  6. [转帖]Linux内存管理(一)——从硬件角度看内存管理

    从硬件角度看内存管理 ①.在操作系统还没有出来之前,程序都是被存放在卡片上,计算机读取一张卡片就运行一条指令.这种从外部存储介质上直接运行指令的方法效率很低 ②.单道编程的内存管理 所谓单道,就是整个 ...

  7. [转帖]实践真知:解决 Jdbc 连接 Oracle 12c 时快时慢的问题

    https://cloud.tencent.com/developer/article/1052506 李真旭@killdb Oracle ACE,云和恩墨技术专家 个人博客:www.killdb.c ...

  8. [转帖]iometer - 性能压力测试工具

    <存储工具系列文章>主要介绍存储相关的测试和调试工具,包括不限于dd.fio.vdbench.iozone.iometer.cosbench等性能负载工具,及strace等调试工具. 1 ...

  9. [转帖]Web性能优化工具WebPageTest(三)——本地部署(Windows 7版本)

    http://www.zlprogram.com/Show/30/30117.shtml 这次先能够使用PC端的浏览器测试,首先需要下载官方的发布版本"WebPageTest 3.0&quo ...

  10. [转帖]一文浅析Nginx线程池!

    https://zhuanlan.zhihu.com/p/616500765     Nginx通过使用多路复用IO(如Linux的epoll.FreeBSD的kqueue等)技术很好的解决了c10k ...