zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    《软件需求分析》阅读笔记
    03软件需求阅读笔记之一
    02软件需求阅读笔记之一
    01软件需求阅读笔记之一
    评价一下大家手头正在使用输入法或者搜索类的软件产品。
    05构建之法阅读笔记之一
    06构建之法阅读笔记之一
    03构建之法阅读笔记之一
    【秋招必备】Java中间件面试题(2021最新版)
    快手3面:说说傅里叶变换、拉普拉斯变换为什么要变换,它们之间的联系是什么!
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9695083.html
Copyright © 2011-2022 走看看