P1073 [NOIP2009 提高組] 最優貿易
題目描述
C國有 n 個大城市和 m 條道路,每條道路連線這 n 個城市中的某兩個城市。任意兩個城市之間最多隻有一條道路直接相連。這 m 條道路中有一部分為單向通行的道路,一部分為雙向通行的道路,雙向通行的道路在統計條數時也計為1條。
C國幅員遼闊,各地的資源分佈情況各不相同,這就導致了同一種商品在不同城市的價格不一定相同。但是,同一種商品在同一個城市的買入價和賣出價始終是相同的。
商人阿龍來到 CCC 國旅遊。當他得知同一種商品在不同城市的價格可能會不同這一資訊之後,便決定在旅遊的同時,利用商品在不同城市中的差價賺回一點旅費。設 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 條道路的資訊(每條道路所連線的兩個城市的編號以及該條道路的通行情況)。請你告訴阿龍,他最多能賺取多少旅費。
輸入格式
第一行包含 22 個正整數 n 和 m,中間用一個空格隔開,分別表示城市的數目和道路的數目。
第二行 n 個正整數,每兩個整數之間用一個空格隔開,按標號順序分別表示這 n 個城市的商品價格。
接下來 m 行,每行有 3 3個正整數x,y,z,每兩個整數之間用一個空格隔開。如果 z=1z=1,表示這條道路是城市 x 到城市 y 之間的單向道路;如果 z=2,表示這條道路為城市 x 和城市y 之間的雙向道路。
輸出格式
一 個整數,表示最多能賺取的旅費。如果沒有進行貿易,則輸出 0。
輸入輸出樣例
輸入
5 5
4 3 5 6 1
1 2 1
1 4 1
2 3 2
3 5 1
4 5 2
輸出
5
說明/提示
【資料範圍】
輸入資料保證 11 號城市可以到達 n 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.
NOIP 2009 提高組 第三題
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iostream>
using namespace std;
const int N = 500000 * 2 + 10;
int e[N],w[N],ne[N],dis[N],h[N],rh[N],idx;
int a[N];
int n,m;
int st[N];
int minn[N],maxx[N];
void add(int h[], int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
void spfa1()//get_minn
{
queue <int> q;
memset(st,0,sizeof(st));
st[1] = 1;
memset(minn,0x3f,sizeof(minn));
minn[1] = a[1];
q.push(1);
while(q.size())
{
int t = q.front();
q.pop();
st[t] = 0;
for(int i = h[t]; ~i ; i = ne[i] )
{
int j = e[i];
if(minn[j] > min(minn[t] , a[j]) )
{
minn[j] = min(minn[t] , a[j]);
if(!st[j])
{
st[j] = 1;
q.push(j);
}
}
}
}
}
void spfa2()//get_maxx
{
queue <int> qq;
memset(st,0,sizeof(st));
st[n] = 1;
qq.push(n);
maxx[n] = a[n];
while(qq.size())
{
int t = qq.front();
//cout<<t<<" ";
qq.pop();
st[t] = 0;
for(int i = rh[t]; ~i ; i = ne[i])
{
int j = e[i];
if(maxx[j] < max(maxx[t] , a[j]))
{
maxx[j] = max(maxx[t] , a[j]);
if(!st[j])
{
st[j] = 1;
qq.push(j);
}
}
}
}
}
int main()
{
scanf("%d %d",&n,&m);
memset(h, -1,sizeof(h));
memset(rh,-1,sizeof(rh));
for(int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
}
for(int i = 1; i <= m; i++)
{
int a, b, c;
scanf("%d %d %d",&a,&b,&c);
if(c == 1)
{
add(h, a, b);
add(rh,b, a);
}
if(c == 2)
{
add(h, a, b);
add(rh,b, a);
add(rh, a, b);
add(h, b, a);
}
}
spfa1();
spfa2();
int ans = 0;
// for(int i = 1; i <= n; i++) printf("%d ",minn[i]);
// printf("\n");
// for(int i = 1; i <= n; i++) printf("%d ",maxx[i]);
// printf("\n");
for(int i = 1; i <= n; i++)
{
ans = max(maxx[i] - minn[i],ans);
}
printf("%d",ans);
return 0;
}