1. 程式人生 > WINDOWS開發 >acwing 341. 最優貿易 圖

acwing 341. 最優貿易 圖

地址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 2
3 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;
}