zoukankan      html  css  js  c++  java
  • NOIP2009最优贸易

    NOIP2009最优贸易

    题目描述

    C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市。任意两个
    城市之间最多只有一条道路直接相连。这m 条道路中有一部分为单向通行的道路,一部分
    为双向通行的道路,双向通行的道路在统计条数时也计为1 条。
    C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价
    格不一定相同。但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。
    商人阿龙来到 C 国旅游。当他得知同一种商品在不同城市的价格可能会不同这一信息
    之后,便决定在旅游的同时,利用商品在不同城市中的差价赚回一点旅费。设C 国n 个城
    市的标号从1~ n,阿龙决定从1 号城市出发,并最终在n 号城市结束自己的旅行。在旅游的
    过程中,任何城市可以重复经过多次,但不要求经过所有n 个城市。阿龙通过这样的贸易方
    式赚取旅费:他会选择一个经过的城市买入他最喜欢的商品——水晶球,并在之后经过的另
    一个城市卖出这个水晶球,用赚取的差价当做旅费。由于阿龙主要是来C 国旅游,他决定
    这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。
    假设 C 国有5 个大城市,城市的编号和道路连接情况如下图,单向箭头表示这条道路
    为单向通行,双向箭头表示这条道路为双向通行。
    
    假设 1~n 号城市的水晶球价格分别为4,3561。
    阿龙可以选择如下一条线路:1->2->3->5,并在2 号城市以3 的价格买入水晶球,在3
    号城市以5 的价格卖出水晶球,赚取的旅费数为2。
    阿龙也可以选择如下一条线路 1->4->5->4->5,并在第1 次到达5 号城市时以1 的价格
    买入水晶球,在第2 次到达4 号城市时以6 的价格卖出水晶球,赚取的旅费数为5。
    
    现在给出 n 个城市的水晶球价格,m 条道路的信息(每条道路所连接的两个城市的编号
    以及该条道路的通行情况)。请你告诉阿龙,他最多能赚取多少旅费。

    solution

    跑两遍spfa。

    第一遍记录从起点到点i的路径上的最小值

    第二遍反向建图,spfa处理出到终点的最大值

    由于好久没写代码了,反向建图时copy的正向的,忘改了,调了半个小时。。。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define MAXN 100010
    #define MAXM 500010
    
    inline int read()
    {
        int f=1,x=0;
        char ch;
        do
        {
            ch=getchar();
            if(ch=='-') f=-1;
        }while(ch<'0'||ch>'9');
        do
        {
            x=(x<<3)+(x<<1)+ch-'0';
            ch=getchar();
        }while(ch>='0'&&ch<='9');
        return f*x;
    }
    
    struct node
    {
        int to;
        int next;
        int val;
    };
    
    int head[MAXN],head1[MAXN],cnt1=0,cnt2=0;
    int n,m;
    node g1[MAXM*2],g2[MAXM*2];
    int v[MAXN];
    int dis[MAXN],dis2[MAXN];
    bool inq[MAXN];
    
    inline void addedge(int a,int b,int v)
    {
        ++cnt1;g1[cnt1].to=b;g1[cnt1].next=head[a];head[a]=cnt1;g1[cnt1].val=v;
        ++cnt2;g2[cnt2].to=a;g2[cnt2].next=head1[b];head1[b]=cnt2;g2[cnt2].val=v;
    }
    
    inline void spfa()
    {
        memset(inq,false,sizeof(inq));
        queue<int>q;
        dis[1]=v[1];
        inq[1]=1;
        q.push(1);
        while(q.size())
        {
            int u=q.front();
            inq[u]=0;
            q.pop();
            for(int i=head[u];i;i=g1[i].next)
            {
                int v=g1[i].to;
                if(dis[v]>min(dis[u],g1[i].val))
                {
                    dis[v]=min(dis[u],g1[i].val);
                    if(!inq[v]) q.push(v),inq[v]=1;
                }
            }
        }
    } 
    
    inline void spfa2()
    {
        memset(inq,false,sizeof(inq));
        queue<int>q;
        dis2[n]=v[n];
        inq[n]=1;
        q.push(n);
        while(q.size())
        {
            int u=q.front();
            inq[u]=0;
            q.pop();
            for(int i=head1[u];i;i=g2[i].next)
            {
                int v=g2[i].to;
                if(dis2[v]<max(dis2[u],g2[i].val))
                {
                    dis2[v]=max(dis2[u],g2[i].val);
                    if(!inq[v]) q.push(v),inq[v]=1;
                }
            }
        }
    } 
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++) v[i]=read();
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read(),z=read();
            if(z==1) addedge(x,y,v[y]);
            if(z==2) addedge(x,y,v[y]),addedge(y,x,v[x]);
        }
        memset(dis,37,sizeof(dis));
        memset(dis2,-37,sizeof(dis2));
        spfa();
        spfa2();
        int ans=0;
        for(int i=1;i<=n;i++)
            ans=max(ans,dis2[i]-dis[i]);
        cout<<ans<<endl;
    }
  • 相关阅读:
    Uni项目启动微信、QQ、淘宝、抖音、京东等APP的方法
    input 标签为checkbox时修改 checkbox的样式
    关于CSS HACK
    前端JS生成可用的MD5加密代码
    把ucharts 封装成组件
    学期总结
    作业1
    作业02
    C语言I博客作业09
    C语言I博客作业08
  • 原文地址:https://www.cnblogs.com/wlzs1432/p/9350837.html
Copyright © 2011-2022 走看看