NOIP 2009 最优贸易 题解

倾然丶 夕夏残阳落幕 提交于 2019-11-28 17:32:35

一道最短路的题,找一个买入和卖出相差最高的点即可,我们先以1为起点跑spfa,d1[x]不再表示距离而表示能够经过权值最小的节点的权值即

if(d1[y]>min(d1[x],price[y])){      d1[y]=min(d1[x],price[y]);      if(!v[y]) q.push(y),v[y]=1; }

我们在建反图,对于n点再跑spfa,算出最大值即

if(d2[y]<max(d2[x],price[y])){     d2[y]=max(d2[x],price[y]);     if(!v[y]) q.push(y),v[y]=1; }

最后枚举每一个节点用d2[x]-d1[x]更新最大值即可

代码

#include<bits/stdc++.h> using namespace std; const int N=100010,M=500010; int tot1,tot2,head[3][N],ver[3][M],Next[3][M]; int d1[N],d2[N],price[N]; bool v[N]; int x,y,z,n,m,ans; queue<int> q; void add1(int x,int y){     ver[1][++tot1]=y;Next[1][tot1]=head[1][x];head[1][x]=tot1; } void add2(int x,int y){     ver[2][++tot2]=y;Next[2][tot2]=head[2][x];head[2][x]=tot2; } void spfa(){     memset(d1,0x3f,sizeof(d1));     d1[1]=price[1];v[1]=1;     q.push(1);     while(!q.empty()){         int x=q.front();q.pop();         v[x]=0;         for(int i=head[1][x];i;i=Next[1][i]){             int y=ver[1][i];             if(d1[y]>min(d1[x],price[y])){                 d1[y]=min(d1[x],price[y]);                 if(!v[y]) q.push(y),v[y]=1;             }         }     }     memset(v,0,sizeof(v));     d2[n]=price[n];v[n]=1;     q.push(n);     while(!q.empty()){         int x=q.front();q.pop();         v[x]=0;         for(int i=head[2][x];i;i=Next[2][i]){             int y=ver[2][i];             if(d2[y]<max(d2[x],price[y])){                 d2[y]=max(d2[x],price[y]);                 if(!v[y]) q.push(y),v[y]=1;             }         }     }        } int main(){     scanf("%d %d",&n,&m);     for(int i=1;i<=n;++i) scanf("%d",&price[i]);     for(int i=1;i<=m;++i){         scanf("%d %d %d",&x,&y,&z);         if(z==1) add1(x,y),add2(y,x);         else{             add1(x,y);add1(y,x);             add2(x,y);add2(y,x);         }     }     spfa();     for(int i=1;i<=n;++i){         ans=max(d2[i]-d1[i],ans);     }     printf("%d",ans);     return 0; }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!