zoukankan      html  css  js  c++  java
  • AcWing341 最优贸易(spfa+dp思想)

    因为这道题只能买卖一次,所以我们可以用dp的思想去分段,也就是以某个位置i作为分段点

    从1-i能找到的最小值和从n-i能找到最大值,答案就是差值,因为两者没有约束。这样可以包含所有情况,虽然要重复。

    问题是如何求去,因为本题有环,所以我们不能真的dp求,而dp其实就是dag的最x路,因此我们可以想到用最长路和最短路来求取

    这种想法可以用spfa实现,不太适合用迪杰斯特拉,因为第一次出队不一定是最小的,这不是传统的最短路,只是想求取路上的最值

    本题建反图来求取最大值,因为如果正着求,最大值不一定是正确的,因为有可能最大值这条路到不了终点,而我们必须要到终点

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define x first
    #define y second
    using namespace std;
    typedef pair<int,int> pll;
    const int N=1e5+10;
    const int M=2e6+10;
    const int inf=0x3f3f3f3f;
    int hl[M],hr[M],ne[M],e[M],w[N],idx;
    int st[N];
    int n,m;
    int dmin[N],dmax[N];
    void add(int h[],int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void spfa(int h[],int dis[],int op){
        queue<int> q;
        if(op==0){
            memset(dis,0x3f,sizeof dmin);
            dis[1]=w[1];
            q.push(1);
        }
        else{
            memset(dis,-0x3f,sizeof dmax);
            dis[n]=w[n];
            q.push(n);
        }
        while(q.size()){
            int t=q.front();
            q.pop();
            int i;
            if(st[t])
                st[t]=0;
            for(i=h[t];i!=-1;i=ne[i]){
                int j=e[i];
                if(op==0){
                    if(dis[j]>min(dis[t],w[j])){// w[j] is for the first time to update himself
                        dis[j]=min(dis[t],w[j]);
                        if(!st[j]){
                            q.push(j);
                            st[j]=1;
                        }
                    }
                }
                else{
                    if(dis[j]<max(dis[t],w[j])){// w[j] is for the first time to update himself
                        dis[j]=max(dis[t],w[j]);
                        if(!st[j]){
                            q.push(j);
                            st[j]=1;
                        }
                    }
                }
            }
        }
    }
    int main(){
        cin>>n>>m;
        int i,j;
        memset(hl,-1,sizeof hl);
        memset(hr,-1,sizeof hr);
        for(i=1;i<=n;i++){
            scanf("%d",&w[i]);
        }
        for(i=1;i<=m;i++){
            int a,b;
            int op;
            scanf("%d%d%d",&a,&b,&op);
            add(hl,a,b),add(hr,b,a);
            if(op==2)
                add(hl,b,a),add(hr,a,b);
        }
        spfa(hl,dmin,0);
        spfa(hr,dmax,1);
        int ans=0;
        for(i=1;i<=n;i++){
            ans=max(ans,dmax[i]-dmin[i]);
        }
        cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    丰清杨 作业 160809315
    自学C++游戏程序开发学习顺序(转)
    哈佛幸福课相关&积极心理学经典英文原版书籍读书笔记(连载中)(转)
    程序员追求的是什么?
    如何学好游戏编程?
    计算机专业的学生必须掌握的五门课程
    [译]学好数学能让程序员的水平更高
    天下没有免费的午餐
    各个类型书籍推荐
    Peter Norvig:自学编程,十年磨一剑
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12822044.html
Copyright © 2011-2022 走看看