AtCoder题解 —— AtCoder Beginner Contest 188 —— E - Peddler —— 动态规划

题目相关

题目链接

AtCoder Beginner Contest 188 E 题,https://atcoder.jp/contests/abc188/tasks/abc188_e

Problem Statement

In Takahashi Kingdom, there are N N N towns, called Town 1 1 1 through Town N N N.
There are also M M M roads in the kingdom, called Road 1 1 1 through Road M M M. By traversing Road i i i, you can travel from Town X i X_i Xi to Town Y i Y_i Yi, but not vice versa. Here, it is guaranteed that X i < Y i X_i<Y_i Xi<Yi.
Gold is actively traded in this kingdom. At Town i i i, you can buy or sell 1 1 1 kilogram of gold for A i A_i Ai yen (the currency of Japan).
Takahashi, a traveling salesman, plans to buy 1 1 1 kilogram of gold at some town, traverse one or more roads, and sell 1 1 1 kilogram of gold at another town.
Find the maximum possible profit (that is, the selling price minus the buying price) in this plan.

Input

Input is given from Standard Input in the following format:

N M
A1 A2 ... AN
X1 Y1
X2 Y2
.
.
.
XM YM

Output

Print the answer.

Sample 1

Sample Input 1

4 3
2 3 1 5
2 4
1 2
1 3

Sample Output 1

3

Explaination

We can achieve the profit of 3 3 3 yen, as follows:
At Town 1 1 1, buy one kilogram of gold for 2 2 2 yen.
Traverse Road 2 2 2 to get to Town 2 2 2.
Traverse Road 1 1 1 to get to Town 4 4 4.
At Town 4 4 4, sell one kilogram of gold for 5 5 5 yen.

Sample 2

Sample Input 2

5 5
13 8 3 15 18
2 4
1 2
4 5
2 3
1 3

Sample Output 2

10

Explaination

We can achieve the profit of 10 10 10 yen, as follows:
At Town 2 2 2, buy one kilogram of gold for 8 8 8 yen.
Traverse Road 1 1 1 to get to Town 4 4 4.
Traverse Road 3 3 3 to get to Town 5 5 5.
At Town 5 5 5, sell one kilogram of gold for 18 18 18 yen.

Sample 3

Sample Input 3

3 1
1 100 1
2 3

Sample Output 3

-99

Explaination

Note that we cannot sell gold at the town where we bought the gold, which means the answer may be negative.

Constraints

  • 2 ≤ N ≤ 2 × 1 0 5 2≤N≤2×10^5 2N2×105
  • 1 ≤ M ≤ 2 × 1 0 5 1≤M≤2×10^5 1M2×105
  • 1 ≤ A i ≤ 1 0 9 1≤A_i≤10^9 1Ai109
  • 1 ≤ X i < Y i ≤ N 1≤Xi<Yi≤N 1Xi<YiN
  • ( X i , Y i ) ≠ ( X j , Y j ) ( i ≠ j ) (Xi,Yi)≠(Xj,Yj)(i≠j) (Xi,Yi)=(Xj,Yj)(i=j)
  • All values in input are integers.

题解报告

题目翻译

在高桥的王国,有 N N N 个城镇,编号从 1 1 1 N N N
在王国里有 M M M 条道路,称为道路 1 1 1 到道路 M M M。穿过第 i i i 条道路,可以从城镇 X i X_i Xi 到城镇 Y i Y_i Yi,但是这第 i i i 条道路,不会从城镇 Y i Y_i Yi X i X_i Xi
在王国里,黄金交易非常活跃。在城镇 i i i,你可以使用 A i A_i Ai 日圆购买 1 1 1 公斤黄金。
高桥,一个旅行商,计划在某个城镇买 1 1 1 公斤黄金,通过一条或者多条道路,在其他城镇卖出这些黄金。
请找出最大的收益。

题目分析

根据题目的描述,找出最大值,基本上就是一个动态规划题目。虽然本题看起来像是数据结构图论方面的内容,DAG 问题。
由于本题有一个限制,也就是 1 ≤ X i < Y i ≤ N 1≤Xi<Yi≤N 1Xi<YiN,我们可以从 N N N 1 1 1 进行动态规划。
假设 D P [ i ] DP[i] DP[i] 为第 i i i 个城镇可以到达的所有城镇中黄金价格最高,不包括第 i i i 个城镇。ans 为 dp[i]-a[i] 的最大值。

样例 1 数据分析

根据样例数据,我们可以绘制出如下的图。
在这里插入图片描述
上图中,黑色表示城镇编号,绿色表示道路,红色表示这个城镇黄金价格。这样我们将有以下两个数据结构,第一个为黄金价格表 a a a

a[i]数值
12
23
31
45

一个是连接矩阵 a d j adj adj

adj[i]
12
3
24

对应的 D P DP DP 数组初始化值都是 -1e9。这样我们从 N N N 1 1 1 ,寻找第 i i i 个城镇相邻的城镇最高黄金价格。如果第 i i i 个城镇没有相连的城镇,就吧 D P DP DP 数组对应值写为 a [ i ] a[i] a[i]

4 4 4 个城镇

由于没有相连的城镇,DP[4]=a[4]。这样 D P DP DP 数组的值变为

DP[i]数值ans
1-1e9-1e9
2-1e9
3-1e9
45
3 3 3 个城镇

由于没有相连的城镇,DP[3]=a[3]。这样 D P DP DP 数组的值变为

DP[i]数值ans
1-1e9-1e9
2-1e9
31
45
2 2 2 个城镇

该城镇可以到城镇 4 4 4,因此,我们取 DP[2] 和 DP[5] 的最大值,也就是 DP[5],即 DP[2]=5。ans 的值也发生改变,变为 max(ans, DP[2]-a[2]),也就是在 2 2 2 城镇买, 5 5 5 城镇卖的差价,也就是 5 − 3 = 2 5-3=2 53=2

DP[i]数值ans
1-1e92
25
31
45
1 1 1 个城镇

该城镇可以到城镇 2 2 2 3 3 3。我们先到城镇 2 2 2,这样 D P [ 1 ] = m a x ( D P [ 1 ] , D P [ 2 ] ) = 5 DP[1]=max(DP[1], DP[2])=5 DP[1]=max(DP[1],DP[2])=5。再到城镇 3 3 3,这样 D P [ 1 ] = m a x ( D P [ 1 ] , D P [ 3 ] ) = 5 DP[1]=max(DP[1], DP[3])=5 DP[1]=max(DP[1],DP[3])=5。这样遍历完连接表,表示从 1 1 1 连接的城镇最高黄金价格为 5 5 5。因此,我们从 1 1 1 城镇购买黄金,到其他城镇卖出,可以获得的价差为 5 − 2 = 3 5-2=3 52=3,跟新 ans 的数据。

DP[i]数值ans
153
25
31
45

数据范围估计

从上面分析中,我们只有减法,而且 A i A_i Ai 的最大数据为 1 0 9 10^9 109,因此 int 可以。

AC 代码

//https://atcoder.jp/contests/abc188/tasks/abc188_e
//E - Peddler Editorial
#include <bits/stdc++.h>

using namespace std;

//如果提交到OJ,不要定义 __LOCAL
//#define __LOCAL

typedef long long ll;

int main() {
#ifndef __LOCAL
    //这部分代码需要提交到OJ,本地调试不使用
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    ll n, m;
    cin>>n>>m;
    vector<int> a(n+1);
    for (int i=1; i<=n; i++) {
        cin>>a[i];
    }

    //连接表
    vector<vector<int>> adj(n+1);
    for (int i=1; i<=m; i++) {
        int u,v;
        cin>>u>>v;
        //建立连接表
        adj[u].emplace_back(v);
    }

    vector<int> dp(n+1, -1e9);//最高价格
    int ans=-1e9;
    for (int i=n; i>=1; i--) {
        //在 adj[i] 中遍历找出黄金最高价
        for (int j=0; j<adj[i].size(); j++){
            dp[i] = max(dp[i], dp[adj[i][j]]);
        }
        ans = max(ans, dp[i]-a[i]);
        dp[i] = max(dp[i], a[i]);//更新价格
    }
    cout<<ans<<"\n";

#ifdef __LOCAL
    //这部分代码不需要提交到OJ,本地调试使用
    system("pause");
#endif
    return 0;
}

在这里插入图片描述

时间复杂度

O ( N + M ) O(N+M) O(N+M)

空间复杂度

O ( N ) O(N) O(N)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值