1. 程式人生 > 其它 >AtCoder題解 —— AtCoder Beginner Contest 188 —— E - Peddler —— 動態規劃

AtCoder題解 —— AtCoder Beginner Contest 188 —— E - Peddler —— 動態規劃

技術標籤:OJ題解# AtCoder題解AtCoder題解ABC188E題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)