acwing 341. 最優貿易 圖
阿新 • • 發佈:2020-06-22
地址https://www.acwing.com/problem/content/343/
C國有 n 個大城市和 m 條道路,每條道路連線這 n 個城市中的某兩個城市。 任意兩個城市之間最多隻有一條道路直接相連。 這 m 條道路中有一部分為單向通行的道路,一部分為雙向通行的道路,雙向通行的道路在統計條數時也計為1條。 C國幅員遼闊,各地的資源分佈情況各不相同,這就導致了同一種商品在不同城市的價格不一定相同。 但是,同一種商品在同一個城市的買入價和賣出價始終是相同的。 商人阿龍來到C國旅遊。 當他得知“同一種商品在不同城市的價格可能會不同”這一資訊之後,便決定在旅遊的同時,利用商品在不同城市中的差價賺一點旅費。 設C國 n 個城市的標號從1~n,阿龍決定從1號城市出發,並最終在 n 號城市結束自己的旅行。 在旅遊的過程中,任何城市可以被重複經過多次,但不要求經過所有 n 個城市。 阿龍通過這樣的貿易方式賺取旅費:他會選擇一個經過的城市買入他最喜歡的商品——水晶球,並在之後經過的另一個城市賣出這個水晶球,用賺取的差價當做旅費。 因為阿龍主要是來C國旅遊,他決定這個貿易只進行最多一次,當然,在賺不到差價的情況下他就無需進行貿易。 現在給出 n 個城市的水晶球價格,m 條道路的資訊(每條道路所連線的兩個城市的編號以及該條道路的通行情況)。 請你告訴阿龍,他最多能賺取多少旅費。 注意:本題資料有加強。 輸入格式 第一行包含2 個正整數 n 和 m,中間用一個空格隔開,分別表示城市的數目和道路的數目。 第二行 n 個正整數,每兩個整數之間用一個空格隔開,按標號順序分別表示這 n 個城市的商品價格。 接下來 m 行,每行有 3 個正整數,x,y,z,每兩個整數之間用一個空格隔開。 如果z=1,表示這條道路是城市 x 到城市 y 之間的單向道路;如果z=2,表示這條道路為城市 x 和城市 y 之間的雙向道路。 輸出格式 一個整數,表示答案。 資料範圍 1≤n≤100000,1≤m≤500000,1≤各城市水晶球價格≤100 輸入樣例: 5 5 4 3 5 6 1 1 2 1 1 4 1 2 3 23 5 1 4 5 2 輸出樣例: 5
解答
將路程分為兩段 前段為購買 後端為賣出
購買是尋找圖的最小權值 賣出則是尋找圖的最大權值
同時還要保證購買賣出點的可達到性
1~k k~n(k= 1,2,3,4......n)
採用spfa 前後雙向遍歷 逆向尋找最大權值 正向尋找最小權值
// 11111111.cpp : 此檔案包含 "main" 函式。程式執行將在此處開始並結束。 // #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int N = 100010,M = 2000010; int n,m; int w[N]; int dmin[N],dmax[N]; queue<int> q; vector<int> gor[N]; vector<int> gre[N]; bool st[N]; /* 5 5 4 3 5 6 1 1 2 1 1 4 1 2 3 2 3 5 1 4 5 2 */ void spfamax(int dist[]) { memset(st,sizeof(st)); memset(dist,-0x3f,sizeof dmax); while (q.size()) q.pop(); dist[n] = w[n]; q.push(n); while (q.size()) { int t = q.front(); q.pop(); st[t] = false; for (int i = 0; i < gre[t].size(); i++) { int j = gre[t][i]; if (dist[j] < max(dist[t],w[j])) { dist[j] = max(dist[t],w[j]); if (!st[j]) { q.push(j); st[j] = true; } } } } } void spfamin(int dist[]) { memset(st,0x3f,sizeof dmin); while (q.size()) q.pop(); dist[1] = w[1]; q.push(1); while (q.size()) { int t = q.front(); q.pop(); st[t] = false; for (int i = 0; i < gor[t].size(); i++) { int j = gor[t][i]; //cout << dist[j] <<" " << dist[t] << " " << w[j] << endl; if (dist[j] > min(dist[t],w[j])) { dist[j] = min(dist[t],w[j]); if (!st[j]) { q.push(j); st[j] = true; } } } } } int main() { ios::sync_with_stdio(false); cin >> n >> m; for (int i = 1; i <= n; i++) cin >> w[i]; while (m--) { int a,b,c; cin >> a >> b >> c; gor[a].push_back(b); gre[b].push_back(a); if (c == 2) { gor[b].push_back(a); gre[a].push_back(b); } } spfamin(dmin); spfamax(dmax); int res = 0; for (int i = 1; i <= n; i++) res = max(res,dmax[i] - dmin[i]); cout << res << endl; return 0; }