P1073 最优贸易

传送门

走一条路线时

肯定先在最便宜的城市买入,然后在最贵的城市卖出

所以我们只要确定一条路径中最便宜的价格和一条路径中最贵的价格

但是要注意一点:先买入,再卖出

可以从起点dfs一波,求出起点到每个点所有路径中,最便宜的价格为多少

然后从终点沿反向边再dfs一波,求出每个点到终点的所有路径中,最贵的价格为多少

然后枚举每个点 i 就好了

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=1e5+7;
const int M=1e6+7;
int n,m,val[N];
int fir[N][2],from[M][2],to[M][2],cnt;//存正向和反向边
inline void add(int a,int b)
{
    from[++cnt][0]=fir[a][0];
    fir[a][0]=cnt; to[cnt][0]=b;
    from[cnt][1]=fir[b][1];
    fir[b][1]=cnt; to[cnt][1]=a;
}

int mival[N],mxval[N];
void dfs1(int x)//确定起点到各个点的路径上的点最小值
{
    for(int i=fir[x][0];i;i=from[i][0])
    {
        int pos=to[i][0],v=min(mival[x],val[pos]);
        if(mival[pos]>v)//显然只有下一个点能更新才需要继续向下DFS
        {
            mival[pos]=v;
            dfs1(pos);
        }
    }
}
void dfs2(int x)//确定终点到各个点的路径上的点最大值
{
    for(int i=fir[x][1];i;i=from[i][1])
    {
        int pos=to[i][1],v=max(mxval[x],val[pos]);
        if(mxval[pos]<v)
        {
            mxval[pos]=v;
            dfs2(pos);
        }
    }
}

int main()
{
    int a,b,c;
    cin>>n>>m;
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        add(a,b);
        if(c==2) add(b,a);
    }

    memset(mival,0x7f,sizeof(mival));
    memset(mxval,0x80,sizeof(mxval));
    mival[1]=val[1]; mxval[n]=val[n];
    dfs1(1); dfs2(n);

    int ans=0;
    for(int i=1;i<=n;i++)
        if(mxval[i]-mival[i]>ans) ans=mxval[i]-mival[i];
    cout<<ans;
    return 0;
}
DFS

当然也可以用最短路来求(速度差不多,dfs会快一点):

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e5+7;
const int M=1e6+7;
int n,m,val[N];
int fir[N][2],from[M][2],to[M][2],cnt;
inline void add(int a,int b)
{
    from[++cnt][0]=fir[a][0];
    fir[a][0]=cnt; to[cnt][0]=b;
    from[cnt][1]=fir[b][1];
    fir[b][1]=cnt; to[cnt][1]=a;
}

//以下几乎就是Dijkstra的模板
struct node
{
    int pos,v;
    bool operator < (const node &b) const{
        return v>b.v;
    }
};
priority_queue <node> q;
int mival[N],mxval[N];
void Dijk1()//确定最小值
{
    memset(mival,0x7f,sizeof(mival));
    mival[1]=val[1]; q.push((node){1,val[1]});
    while(!q.empty())
    {
        node u=q.top(); q.pop();
        if(u.v!=mival[u.pos]) continue;
        for(int i=fir[u.pos][0];i;i=from[i][0])
        {
            int pos=to[i][0],v=min(u.v,val[pos]);
            if(mival[pos]>v)
            {
                mival[pos]=v;
                q.push((node){pos,v});
            }
        }
    }
}
void Dijk2()//确定最大值
{
    memset(mxval,0x80,sizeof(mxval));
    mxval[n]=val[n]; q.push((node){n,val[n]});
    while(!q.empty())
    {
        node u=q.top(); q.pop();
        if(u.v!=mxval[u.pos]) continue;
        for(int i=fir[u.pos][1];i;i=from[i][1])
        {
            int pos=to[i][1],v=max(u.v,val[pos]);
            if(mxval[pos]<v)
            {
                mxval[pos]=v;
                q.push((node){pos,v});
            }
        }
    }
}

int main()
{
    int a,b,c;
    cin>>n>>m;
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        add(a,b);
        if(c==2) add(b,a);
    }

    Dijk1(); Dijk2();

    int ans=0;
    for(int i=1;i<=n;i++)
        if(mxval[i]-mival[i]>ans) ans=mxval[i]-mival[i];
    cout<<ans;
    return 0;
}
Dijkstra
原文地址:https://www.cnblogs.com/LLTYYC/p/9695083.html