• NOIP最优贸易


    #include<cstdio>
    #define MXN 100000+1
    #define MXM 10*MXN
    int getint(){
        int x=0,w=1;
        char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-') w=0;
            c=getchar();
        }
        while(c>='0'&&c<='9'){
            x=(x<<3)+(x<<1)+(c-'0');
            c=getchar();
        }
        return w?x:-x;
    }
    void write(int x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return;
    }
    int n,m,x,y,z,p,end;
    int price[MXN],dis[3*MXN+2];
    bool vis[3*MXN+2];
    int queue[MXM],head,tail;
    int u[3*MXM+2],v[3*MXM+2],w[3*MXM+2],fst[3*MXN+2],nxt[3*MXM+2],top;
    void add(int x,int y,int z){
        top++;
        u[top]=x,v[top]=y,w[top]=z;
        nxt[top]=fst[u[top]];
        fst[u[top]]=top;
        return;
    }
    void spfa(){
        for(int i=2;i<=3*n+1;i++) dis[i]=2000000000;
        dis[1]=0;
        vis[1]=true;
        queue[tail++]=1;
        int now;
        while(head!=tail){
            now=queue[head];
            vis[now]=false;
            for(int i=fst[now];i;i=nxt[i]){
                if(dis[v[i]]>dis[now]+w[i]){
                    dis[v[i]]=dis[now]+w[i];
                    if(vis[v[i]]==false){
                        queue[tail]=v[i];
                        vis[v[i]]=true;
                        tail=tail+1==MXM ? 0 : tail+1;
                    }
                }
            }
            head=head+1==MXM ? 0 : head+1;
        }
        return;
    }
    int main(){
        n=getint(),m=getint();
        for(int i=1;i<=n;i++) price[i]=getint();
        for(int i=0;i<m;i++){
            x=getint(),y=getint(),p=getint();
            if(p==1){
                add(x,y,0),add(x+n,y+n,0),add(x+2*n,y+2*n,0);
                add(x,y+n,price[x]),add(x+n,y+2*n,-price[x]);
            }
            if(p==2){
                add(x,y,0),add(y,x,0);
                add(x+n,y+n,0),add(y+n,x+n,0);
                add(x+2*n,y+2*n,0),add(y+2*n,x+2*n,0);
                add(x,y+n,price[x]),add(y,x+n,price[y]);
                add(x+n,y+2*n,-price[x]),add(y+n,x+2*n,-price[y]);
            }
        }
        end=3*n+1;
        add(n,end,0),add(3*n,end,0);
        spfa();
        write(-dis[end]);
        return 0;
    }
    AC代码

    这是一道图论题。

    题意是:有n个城市之间有m条道路,每个城市都可以买到一种商品叫水晶球,同时也可以卖出水晶球,买卖价格相同但各个城市之间价格不同,记为price。商人阿龙于是准备在旅游期间倒卖水晶球。他想好好享受旅游,所以只准备做一次交易(即买一次卖一次)。他的旅行路线是从城市1到城市n,但既不必每个城市都去,也不限制每个城市只去一次。有时候城市之间的道路是单向的,但有时是双向的,但无论怎么样都算作一条道路。

    输入n,m,下一行输入各城市水晶球的价格,下m行每行输入x,y,z,表示x,y之间有一条道路,z=1时指单向,z=2时指双向。

    输出阿龙一次交易可以赚得的最大差价。

    虽然第一眼看这道题,感觉有点像本人之前做过的一道题,那道题题解是把spfa的dis数组改成二维的了。但是发现不能这么做,因为完全不一样ORZ……

    看了别人题解发现这道题可以用分层图来做:第一层表示买之前,第二层表示卖之前,第三层表示卖之后。若x→y,则在第一层x连接一条到第二层y的边权为price[x]的边,并在第二层x连接一条到第三层y的边权为-price[x]的边。同层之间连接0权边。最后设置汇点T,使第一层的点n和第三层的点n连接到T,从第一层点1开始spfa。

    由于题里说阿龙也可以不做买卖,所以第一层的n也连接T

    由于这样跑最短路跑出来的dis[T]≤0,所以最后输出相反数。也可以把一、二层之间的边改为负数,二、三层之间改为正数跑最长路。

    这道题很有趣,用分层图做代码短效率高,非常舒服。

  • 相关阅读:
    【Demo】QQ,github,微博第三方社交登录
    crontab执行时间和系统时间不一致
    CDN服务技术架构图
    【php】命名空间 和 自动加载的关系
    【运维工具】Git代码发布系统
    【ipv6惹的祸】curl 超时
    MySQL:动态开启慢查询日志(Slow Query Log)
    Virtualbox 虚拟机支持硬件摄像头
    网页取消快照、禁止抓取等meta标签功能
    ajax 跨域
  • 原文地址:https://www.cnblogs.com/halifuda/p/8215650.html
Copyright © 2020-2023  润新知