CQNK圖論 2【NOIP2009】最優貿易
阿新 • • 發佈:2020-12-28
技術標籤:c++
【問題描述】
C國有n個大城市和m條道路,每條道路連線這n個城市中的某兩個城市。任意兩個城市之間最多隻有一條道路直接相連。這m條道路中有一部分為單向通行的道路,一部分為雙向通行的道路,雙向通行的道路在統計條數時也計為1條。
C國幅員遼闊,各地的資源分佈情況各不相同,這就導致了同一種商品在不同城市的價格不一定相同。但是,同一種商品在同一個城市的買入價和賣出價始終是相同的。
商人阿龍來到C國旅遊。當他得知同一種商品在不同城市的價格可能會不同這一資訊之後,便決定在旅遊的同時,利用商品在不同城市中的差價賺回一點旅費。設C國n個城市的標號從1-n,阿龍決定從1號城市出發,並最終在n號城市結束自己的旅行。在旅遊的過程中,任何城市可以重複經過多次,但不要求經過所有n個城市。阿龍通過這樣的貿易方式賺取旅費:他會選擇一個經過的城市 買入他最喜歡的商品——水晶球,並在之後經過的另一個城市賣出這個水晶球。用賺取的差價當作旅費。由於阿龍主要是來C國旅遊,他決定這個貿易只進行最多一次。當然,在賺不到差價的情況下它就無需進行貿易。
假設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條道路的資訊(每條道路所連線的兩個城市的編號以及該條道路的通行情況)。請你告訴阿龍,他最多能賺錢多少旅費。
本題主要是求最低買進價以及最高賣出價,同時要求到n。
(編不下去了,上程式碼)
#include <bits/stdc++.h> using namespace std; const int MAXN = 500000+5; int n,m,e = 1,ans,ms[MAXN][2],Sell[MAXN],Buy[MAXN],Price[MAXN];//ms用來儲存正反圖 bool mark[MAXN];`` queue<int>q; struct node{ int v,next; }edge[MAXN]; void connect(int u,int v){ edge[e].next = ms[u][0];edge[e].v = v;ms[u][0] = e++;//最短路默寫同款 edge[e].next = ms[v][1];edge[e].v = u;ms[v][1] = e++; } void spfa_1(){ q.push(1); mark[1] = true; Buy[1] = Price[1]; while(!q.empty()){ int x = q.front();q.pop(); mark[x] = false; for(int i = ms[x][0];i;i = edge[i].next){//最短路默寫同款 int v = edge[i].v; if(Buy[v]>min(Buy[x],Price[v])){ Buy[v] = min(Buy[x],Price[v]); if(!mark[v]) q.push(v),mark[v] = true; } } } } void spfa_2(){ q.push(n); mark[n] = true; Sell[n] = Price[n]; ans = max(ans,Sell[n] - Buy[n]); //強迫症當場去世 while(!q.empty()){ int x = q.front();q.pop(); mark[x] = false; for(int i = ms[x][1];i;i = edge[i].next){//最短路默寫同款 int v = edge[i].v; if(Sell[v]<max(Sell[x],Price[v])){ Sell[v] = max(Sell[x],Price[v]); ans = max(Sell[v] - Buy[v],ans);//再死一次 if(!mark[v]) q.push(v),mark[v] = true; } } } } int main() { scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++){ scanf("%d",&Price[i]),Buy[i] = 105; } int u,v,k; for(int i = 1;i <= m;i++){ scanf("%d%d%d",&u,&v,&k); connect(u,v); if(k == 2) connect(v,u); } memset(mark,0,sizeof(mark)); spfa_1(); memset(mark,0,sizeof(mark)); spfa_2(); printf("%d\n",ans); return 0; } //記得關注博主