1. 程式人生 > 其它 >CQNK圖論 2【NOIP2009】最優貿易

CQNK圖論 2【NOIP2009】最優貿易

技術標籤:c++

【問題描述】
  C國有n個大城市和m條道路,每條道路連線這n個城市中的某兩個城市。任意兩個城市之間最多隻有一條道路直接相連。這m條道路中有一部分為單向通行的道路,一部分為雙向通行的道路,雙向通行的道路在統計條數時也計為1條。
  C國幅員遼闊,各地的資源分佈情況各不相同,這就導致了同一種商品在不同城市的價格不一定相同。但是,同一種商品在同一個城市的買入價和賣出價始終是相同的。
  商人阿龍來到C國旅遊。當他得知同一種商品在不同城市的價格可能會不同這一資訊之後,便決定在旅遊的同時,利用商品在不同城市中的差價賺回一點旅費。設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條道路的資訊(每條道路所連線的兩個城市的編號以及該條道路的通行情況)。請你告訴阿龍,他最多能賺錢多少旅費。

 解題思路
 本題主要是求最低買進價以及最高賣出價,同時要求到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;
}
//記得關注博主