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;
}
原文地址:https://www.cnblogs.com/wlzs1432/p/9350837.html