VIJOS 1754 最優貿易_VIJOS

來源:互聯網
上載者:User
 描述

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條道路的資訊(每條道路所串連的兩個城市的編號
以及該條道路的通行情況) 。請你告訴阿龍,他最多能賺取多少旅費。 格式 輸入格式

第一行包含 2 個正整數 n 和 m,中間用一個空格隔開,分別表示城市的數目和道路的
數目。 
第二行 n 個正整數,每兩個整數之間用一個空格隔開,按標號順序分別表示這 n 個城
市的商品價格。 
接下來 m行, 每行有 3 個正整數, x, y, z, 每兩個整數之間用一個空格隔開。 如果 z=1,
表示這條道路是城市 x到城市 y之間的單向道路;如果 z=2,表示這條道路為城市 x 和城市
y之間的雙向道路。 輸出格式

輸出共1 行, 包含 1 個整數, 表示最多能賺取的旅費。 如果沒有進行貿易,
則輸出 0。 範例 範例輸入

5 5 4 3 5 6 1 1 2 1 1 4 1 2 3 2 3 5 1 4 5 2 
範例輸出
5
限制

每個測試點1s 來源

NOIP 2009




想著學學Tarjan吧 於是寫了個縮點+DP

然後喜聞樂見的爆0了

哈哈哈哈哈哈哈哈

不作死就不會死。。。


tarjan寫的沒錯 錯在dp了

一開始喪心病狂的從1遞推 每一個點取最大值

後來發現必須停到n

也就是說必須做完交易後能走到n

也就是說 連反向邊 可以從n走到交易點

所以就倒著DP啦。。。。


#include<iostream>#include<cstdio>#include<cstring>#include<stack>#include<cstdlib>#include<algorithm>using namespace std;const int lim=100011;struct self{int x,y;}s[lim*10],k[lim*10];int firsts[lim*10],nxts[lim*10];int firstk[lim*10],nxtk[lim*10];int ss,kk;int w[lim];int scc[lim],pre[lim],low[lim],maxv[lim],minv[lim];int m,n,a,b,c,sccnt,dfstime,x,y,z;stack<int>S;void tarjan(int i){    dfstime++;    pre[i]=low[i]=dfstime;    S.push(i);    for(int e=firsts[i];e!=-1;e=nxts[e])    {        if(!pre[s[e].y])        {            tarjan(s[e].y);            low[i]=min(low[i],low[s[e].y]);        }        else if(!scc[s[e].y])        low[i]=min(low[i],pre[s[e].y]);    }    if(low[i]==pre[i])    {        sccnt++;        for(;;)        {            int x=S.top();S.pop();            scc[x]=sccnt;            maxv[sccnt]=max(w[x],maxv[sccnt]);            if(minv[sccnt]==0)minv[sccnt]=w[x];else minv[sccnt]=min(w[x],minv[sccnt]);            if(x==i)break;        }    }}void makesides(int x,int y){    ss++;s[ss].x=x;s[ss].y=y;    nxts[ss]=firsts[x];    firsts[x]=ss;}void makesidek(int x,int y){    kk++;k[kk].x=x;k[kk].y=y;    nxtk[kk]=firstk[x];    firstk[x]=kk;}int f[lim],ans;int findmin(int i){    if(f[i]!=-1)return f[i];    f[i]=minv[i];    for(int e=firstk[i];e!=-1;e=nxtk[e])    f[i]=min(f[i],findmin(k[e].y));    ans=max(ans,maxv[i]-f[i]);    return f[i];}int main(){    memset(firsts,-1,sizeof(firsts));    memset(nxts,-1,sizeof(nxts));    memset(firstk,-1,sizeof(firstk));    memset(nxtk,-1,sizeof(nxtk));    scanf("%d%d",&m,&c);    for(a=1;a<=m;a++)scanf("%d",&w[a]);        for(a=1;a<=c;a++)    {        scanf("%d%d%d",&x,&y,&z);        makesides(x,y);        if(z==2)makesides(y,x);    }    for(a=1;a<=m;a++)if(!pre[a])tarjan(a);    for(a=1;a<=m;a++)        for(int e=firsts[a];e!=-1;e=nxts[e])        if(scc[a]!=scc[s[e].y])        makesidek(scc[s[e].y],scc[a]);    memset(f,-1,sizeof(f));    findmin(scc[m]);    cout<<ans<<endl;    return 0;}




然後說下喜聞樂見的SPFA做法

(借用spfa的思想 更新走到每個點的最值)

Spfa可以一遍找到每個點的最大最小值

不過這個是有錯誤的吧 因為最後要走到n

可以從1走到i交易 但是可能從i走不到n 這時候就喜聞樂見了

不過由於資料弱 (-.-) 居然可以AC。。。


還有一個是兩次spfa的

第一次從1走找最小值

第二次從n走找最大值

這個應該是不存在什麼問題的吧

然後我嘗試寫了一下

感覺寫起來還不錯。

#include<iostream>#include<cstdio>#include<cstring>#include<stack>#include<cstdlib>#include<algorithm>#include<queue>using namespace std;const int lim=100011;const int inf=999999999;struct self{int x,y;}s[lim*10],k[lim*10];int firsts[lim*10],nxts[lim*10];int firstk[lim*10],nxtk[lim*10];int ss,kk;int w[lim];int maxv[lim],minv[lim];int m,n,a,b,c,x,y,z,ans;void makesides(int x,int y){    ss++;s[ss].x=x;s[ss].y=y;    nxts[ss]=firsts[x];    firsts[x]=ss;}void makesidek(int x,int y){    kk++;k[kk].x=x;k[kk].y=y;    nxtk[kk]=firstk[x];    firstk[x]=kk;}queue<int>q;bool inq[lim];void spfamin(){    int a;    memset(inq,0,sizeof(inq));    q.push(1);inq[1]=1;    for(a=1;a<=m;a++)minv[a]=inf;    minv[1]=w[1];    while(!q.empty())    {        int u=q.front();q.pop();        for(int e=firsts[u];e!=-1;e=nxts[e])        if(minv[s[e].y]>minv[u])        {            minv[s[e].y]=min(minv[u],w[s[e].y]);            if(!inq[s[e].y])            {                inq[s[e].y]=1;                q.push(s[e].y);            }        }    }}void spfamax(){    int a;    memset(inq,0,sizeof(inq));    q.push(m);inq[m]=1;    for(a=1;a<=m;a++)maxv[a]=-inf;    maxv[m]=w[m];    while(!q.empty())    {        int u=q.front();q.pop();        for(int e=firstk[u];e!=-1;e=nxtk[e])        if(maxv[k[e].y]<maxv[u])        {            maxv[k[e].y]=max(maxv[u],w[k[e].y]);            if(!inq[k[e].y])            {                inq[k[e].y]=1;                q.push(k[e].y);            }        }    }}int main(){    memset(firsts,-1,sizeof(firsts));    memset(nxts,-1,sizeof(nxts));    memset(firstk,-1,sizeof(firstk));    memset(nxtk,-1,sizeof(nxtk));    scanf("%d%d",&m,&c);    for(a=1;a<=m;a++)scanf("%d",&w[a]);    for(a=1;a<=c;a++)    {        scanf("%d%d%d",&x,&y,&z);        makesides(x,y);        makesidek(y,x);        if(z==2)        {            makesides(y,x);            makesidek(x,y);        }    }        spfamin();    spfamax();        for(a=1;a<=m;a++)ans=max(ans,maxv[a]-minv[a]);    cout<<ans<<endl;    return 0;}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.