【SPFA】最优贸易(luogu 1073)
最優(yōu)貿(mào)易
luogu 1073
題目大意:
有n個城市和m條線路連接著這些城市(當編號為1時是有向,2時是無向),從1城市出發(fā)到n城市,每個城市都有固定的水晶球價格(進價和售價一樣),從路過的一個城市買下水晶球,然后在接下來的某個城市賣出(只能進行一次買賣),問最多賺多少錢,當買賣一定虧本時,則輸出0
原題:
題目描述
C C國有 n n個大城市和 mm 條道路,每條道路連接這 nn個城市中的某兩個城市。任意兩個城市之間最多只有一條道路直接相連。這 mm 條道路中有一部分為單向通行的道路,一部分為雙向通行的道路,雙向通行的道路在統(tǒng)計條數(shù)時也計為 1 1條。
C C國幅員遼闊,各地的資源分布情況各不相同,這就導致了同一種商品在不同城市的價格不一定相同。但是,同一種商品在同一個城市的買入價和賣出價始終是相同的。
商人阿龍來到 CC 國旅游。當他得知同一種商品在不同城市的價格可能會不同這一信息之后,便決定在旅游的同時,利用商品在不同城市中的差價賺回一點旅費。設 CC 國 n 個城市的標號從 1~ n1 n,阿龍決定從 1 1號城市出發(fā),并最終在 nn 號城市結束自己的旅行。在旅游的過程中,任何城市可以重復經(jīng)過多次,但不要求經(jīng)過所有 nn 個城市。阿龍通過這樣的貿(mào)易方式賺取旅費:他會選擇一個經(jīng)過的城市買入他最喜歡的商品――水晶球,并在之后經(jīng)過的另一個城市賣出這個水晶球,用賺取的差價當做旅費。由于阿龍主要是來 CC 國旅游,他決定這個貿(mào)易只進行最多一次,當然,在賺不到差價的情況下他就無需進行貿(mào)易。
假設 C C國有 55個大城市,城市的編號和道路連接情況如下圖,單向箭頭表示這條道路為單向通行,雙向箭頭表示這條道路為雙向通行。
假設 1~n1 n 號城市的水晶球價格分別為 4,3,5,6,14,3,5,6,1。
阿龍可以選擇如下一條線路:11->22->33->55,并在 2 2號城市以 33 的價格買入水晶球,在 33號城市以 5 5的價格賣出水晶球,賺取的旅費數(shù)為 2。
阿龍也可以選擇如下一條線路 11->44->55->44->55,并在第1 1次到達 55 號城市時以 1 1的價格買入水晶球,在第 22 次到達 44 號城市時以 66 的價格賣出水晶球,賺取的旅費數(shù)為 55。
現(xiàn)在給出 n n個城市的水晶球價格,mm 條道路的信息(每條道路所連接的兩個城市的編號以及該條道路的通行情況)。請你告訴阿龍,他最多能賺取多少旅費。
輸入輸出格式
輸入格式:
第一行包含 22 個正整數(shù) n n和 mm,中間用一個空格隔開,分別表示城市的數(shù)目和道路的數(shù)目。
第二行 n 個正整數(shù),每兩個整數(shù)之間用一個空格隔開,按標號順序分別表示這 n 個城市的商品價格。
接下來 mm 行,每行有 3 3個正整數(shù)x,y,zx,y,z,每兩個整數(shù)之間用一個空格隔開。如果 z=1z=1,表示這條道路是城市 x x到城市 y y之間的單向道路;如果 z=2z=2,表示這條道路為城市 x x和城市y y之間的雙向道路。
輸出格式:
一 個整數(shù),表示最多能賺取的旅費。如果沒有進行貿(mào)易,則輸出 00。
輸入輸出樣例
輸入樣例#1:
5 5 4 3 5 6 1 1 2 1 1 4 1 2 3 2 3 5 1 4 5 2輸出樣例#1:
5說明
【數(shù)據(jù)范圍】
輸入數(shù)據(jù)保證 11 號城市可以到達 n n號城市。
對于 10%的數(shù)據(jù),1≤n≤61≤n≤6。
對于 30%的數(shù)據(jù),1≤n≤1001≤n≤100。
對于 50%的數(shù)據(jù),不存在一條旅游路線,可以從一個城市出發(fā),再回到這個城市。
對于 100%的數(shù)據(jù),1≤n≤1000001≤n≤100000,1≤m≤5000001≤m≤500000,1≤x1≤x,y≤ny≤n,1≤z≤21≤z≤2,1≤1≤各城市
水晶球價格≤100≤100。
NOIP 2009 提高組 第三題
解題思路:
記錄下每個城市水晶球的價格,用一個minn來存取,從1城市到當前城市的最小買入(要先預處理,賦為一個大于100的值),然后用best來代表從1城市到當前城市做完買賣的最大收入,當當前城市的最小買入或者可以到達的城市的價格小于可以到達的城市的最小買入,就代替掉它,然后best=best和這個城市的水晶球價格減去最小買入,然后當當前城市的最大收入大于可以到達的城市的最大收入就代替并入隊
代碼:
#include<cstdio> #include<cstring> #include<queue> #include<iostream> using namespace std; int n,m,x,y,c,w,now,b[100005],head[100005],p[100005]; struct rec {int to,next; }a[1000005]; struct recc {int minn,best; }f[100005]; int main() {scanf("%d %d",&n,&m);for (int i=1;i<=n;++i){scanf("%d",&b[i]);f[i].minn=2147483647;//初始值}for (int i=1;i<=m;++i){scanf("%d %d %d",&x,&y,&c);a[++w].to=y;//鏈表存法a[w].next=head[x];head[x]=w;if (c==2){a[++w].to=x;//反向a[w].next=head[y];head[y]=w;}}f[1].minn=b[1];//預處理p[1]=1;//記錄queue<int> d;d.push(1);//入隊while (!d.empty()){now=d.front();//取出來d.pop();for (int i=head[now];i;i=a[i].next){if (min(f[now].minn,b[a[i].to])<f[a[i].to].minn)//最小買入{f[a[i].to].minn=min(f[now].minn,b[a[i].to]);f[a[i].to].best=max(f[a[i].to].best,b[a[i].to]-f[a[i].to].minn);//取最小值if (!p[a[i].to]){p[a[i].to]=1;d.push(a[i].to);}}if (f[now].best>f[a[i].to].best)//最大收入{f[a[i].to].best=f[now].best;if (!p[a[i].to]){p[a[i].to]=1;d.push(a[i].to);}}}p[now]=0;}printf("%d",f[n].best);//輸出 }備注:
還有一種方法是從前面往后SPFA找最小買入,從后面往前SPFA找最大賣出,然后搜每一個點,找出一個最大賣出比最小買入多得最多的點,輸出最大賣出比最小買入多的,但因為本人太水,就不寫了
總結
以上是生活随笔為你收集整理的【SPFA】最优贸易(luogu 1073)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【最短路】【SPFA】电车 (luogu
- 下一篇: 让旧电脑如苹果Mac般流畅!一个良心小工