zoukankan      html  css  js  c++  java
  • [NOIp2009] 最优贸易

    传送门:>Here<

    给出一张有向图($n leq 10^5, m leq 5 cdot 10^5$),每个点有两个点权——水晶买入价和水晶卖出价。一个商人从1走到n,点和边可以重复走,在某个点买进,在另一个店卖出。问其能赚到的最大差价。

    解题思路

    如果我们枚举买进点$i$,那么接下来就是要在$i ightarrow n$中寻找卖出价的最大值。从各个点到一个固定点的路径问题,最适合采用`反向建边`。因此我们反向建边做一下。

    而还要注意$i$必须是从1出发可达的(有向图存在连通性问题)。因此正向边也要做一下。

    代码注意点

      SPFA做的是边权,而这里是点权。要注意转换。

    $Code$

    /*By QiXingzhi*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    const int N = 100010;
    const int INF = 715827882;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
        return x * w;
    }
    bool inQ[N];
    int n,m,ans,x,y,z;
    int a[N],maxx[N],minx[N];
    vector <int> G[N];
    vector <int> G2[N];
    queue <int> q;
    inline void AddEdge(int u, int v){
        G[u].push_back(v);
        G2[v].push_back(u);
    }
    inline void SPFA1(int s){
        memset(minx,0x3f,sizeof(minx));
        minx[s] = a[s];
        q.push(s);
        inQ[s] = 1;
        int cur,to,sz;
        while(!q.empty()){
            cur = q.front();
            q.pop();
            inQ[cur] = 0;
            sz = G[cur].size();
            for(int i = 0; i < sz; ++i){
                to = G[cur][i];
                if(minx[cur] < minx[to]){
                    minx[to] = Min(minx[cur], a[to]);
                    if(!inQ[to]){
                        q.push(to);
                        inQ[to] = 1;
                    }
                }
            }
        }
    }
    inline void SPFA2(int s){
        memset(inQ,0,sizeof(inQ));
        while(!q.empty()) q.pop();
         maxx[s] = a[s];
        q.push(s);
        inQ[s] = 1;
        int cur,to,sz;
        while(!q.empty()){
            cur = q.front();
            q.pop();
            inQ[cur] = 0;
            sz = G2[cur].size();
            for(int i = 0; i < sz; ++i){
                to = G2[cur][i];
                if(maxx[cur] > maxx[to]){
                    maxx[to] = Max(maxx[cur],a[to]);
                    if(!inQ[to]){
                        q.push(to);
                        inQ[to] = 1;
                    }
                }
            }
        }
    }
    int main(){
        //freopen(".in","r",stdin);
        n = r, m = r;
        for(int i = 1; i <= n; ++i) a[i] = r;
        for(int i = 1; i <= m; ++i){
            x = r, y = r, z = r;
            AddEdge(x,y);
            if(z == 2){
                AddEdge(y,x);
            }
        }
        SPFA1(1);
        SPFA2(n);
        for(int i = 1; i <= n; ++i){
            ans = Max(ans, maxx[i]-minx[i]);
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Dockerfile深度剖析
    centos 7安装jdk8
    Centos 7 修改YUM镜像源地址为阿里云镜像地址
    Fabric智能合约(余额转移样本)
    Fabric智能合约(base)
    Fabric背书策略文件编写说明
    多catch块折叠
    Frp内网穿透服务部署
    Linux常用命令合集(初级)--Centos版
    English trip EM3-LP-5A Shopping Teacher: GABRIELE
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9279635.html
Copyright © 2011-2022 走看看