• CH6101 最优贸易


    描述

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

    输入格式

       第一行包含 2 个正整数n 和m,中间用一个空格隔开,分别表示城市的数目和道路的
    数目。
       第二行 n 个正整数,每两个整数之间用一个空格隔开,按标号顺序分别表示这n 个城
    市的商品价格。
       接下来 m 行,每行有3 个正整数,x,y,z,每两个整数之间用一个空格隔开。如果z=1,表示这条道路是城市x 到城市y 之间的单向道路;如果z=2,表示这条道路为城市x 和城市y 之间的双向道路

    输出格式

    一个整数,表示答案。

    样例输入

    5 5
    4 3 5 6 1
    1 2 1
    1 4 1
    2 3 2
    3 5 1
    4 5 2

    样例输出

    5

    数据范围与约定

    • 输入数据保证 1 号城市可以到达n 号城市。
      对于 10%的数据,1≤n≤6。
      对于 30%的数据,1≤n≤100。
      对于 50%的数据,不存在一条旅游路线,可以从一个城市出发,再回到这个城市。
      对于 100%的数据,1≤n≤100000,1≤m≤500000,1≤x,y≤n,1≤z≤2,1≤各城市
      水晶球价格≤100。

    测试地址:CH6101


    如果题意莫名其妙,那么莫名其妙的不是出题人的脑袋就是我们的脑袋。——zrt

    个人思路:

    • 注意到进行最多一次最多能赚取和输入格式,可以考虑一下单源最短路径。
    • 假设我们是阿龙 的话,当然会在路径上选择最便宜的地方买物品,最贵的地方售出物品。
    • 如果对Dijkstra的更新方式进行修改,就可以求出从源点到每一个点购入的最便宜价格。(对Dijkstra的理解)
    • 形象地说,我们如果是阿龙的话,等于尝试走到每个点,并看从源点到每个点时,能购入的最便宜价格。
    • 到这里,就有一个小技巧了。既然求得购入价格可以正着走,那么是否求售出价格可以反着走呢?
    • 答案是可以的。
    • 最终,进行两次Dijkstra,再枚举ans=max(售出价格[i]-购入价格[i])即可求出答案。注意,第二次Dijkstra要求进行在反图上。

    #include<cstdio>
    #include<iostream>
    #include<queue>
    using namespace std;
    const int MAXN=1000010,MAXM=1000010;
    int n;
    struct Edge_Low{
    	int from,to,nxt;
    }e_Low[MAXM];
    int head_Low[MAXN],edgeCnt_Low=0;
    void addEdge_Low(int u,int v){
    	e_Low[++edgeCnt_Low].from=u;
    	e_Low[edgeCnt_Low].to=v;
    	e_Low[edgeCnt_Low].nxt=head_Low[u];
    	head_Low[u]=edgeCnt_Low;
    }
    int price[MAXN];//各个点的价格 
    const int INF=2100000000;
    struct Node{
    	int nowPoint,nowValue;
    	bool operator <(const Node &a)const{
    		return a.nowValue<nowValue;
    	}
    };
    int s_Low;
    int dis_Low[MAXN];
    void dijkstra_Low(){//收购尽量低价 
    	for(int i=1;i<=n;i++)dis_Low[i]=INF;
    	priority_queue<Node> q;
    	q.push(Node{s_Low,price[s_Low]});dis_Low[s_Low]=price[s_Low];
    	while(!q.empty()){
    		Node nowNode=q.top();q.pop();
    		int nowPoint=nowNode.nowPoint,nowValue=nowNode.nowValue;
    		if(dis_Low[nowPoint]!=nowValue)continue;
    		for(int i=head_Low[nowPoint];i;i=e_Low[i].nxt){
    			int nowV=e_Low[i].to;
    			if(dis_Low[nowV]>dis_Low[nowPoint]){
    				dis_Low[nowV]=min(dis_Low[nowPoint],price[nowV]);
    				q.push(Node{nowV,dis_Low[nowV]});
    			}
    		}
    	}
    }
    struct Edge_High{
    	int from,to,nxt;
    }e_High[MAXM];
    int head_High[MAXN],edgeCnt_High=0;
    void addEdge_High(int u,int v){
    	e_High[++edgeCnt_High].from=u;
    	e_High[edgeCnt_High].to=v;
    	e_High[edgeCnt_High].nxt=head_High[u];
    	head_High[u]=edgeCnt_High;
    }
    int s_High;
    int dis_High[MAXN];
    void dijkstra_High(){//售出尽量高价 
    	for(int i=1;i<=n;i++)dis_High[i]=-INF;
    	priority_queue<Node> q;
    	q.push(Node{s_High,price[s_High]});dis_High[s_High]=price[s_High];
    	while(!q.empty()){
    		Node nowNode=q.top();q.pop();
    		int nowPoint=nowNode.nowPoint,nowValue=nowNode.nowValue;
    		if(dis_High[nowPoint]!=nowValue)continue;
    		for(int i=head_High[nowPoint];i;i=e_High[i].nxt){
    			int nowV=e_High[i].to;
    			if(dis_High[nowV]<dis_High[nowPoint]){
    				dis_High[nowV]=max(dis_High[nowPoint],price[nowV]);
    				q.push(Node{nowV,dis_High[nowV]});
    			}
    		}
    	}
    }
    int main(){
    	int m;
    	scanf("%d%d",&n,&m);
    	s_Low=1,s_High=n;
    	for(int i=1;i<=n;i++)scanf("%d",&price[i]);
    	for(int i=1;i<=m;i++){
    		int u,v,z;
    		scanf("%d%d%d",&u,&v,&z);
    		addEdge_Low(u,v);
    		addEdge_High(v,u);
    		if(z==2){
    			addEdge_Low(v,u);
    			addEdge_High(u,v);
    		}
    	}
    	dijkstra_Low();
    	dijkstra_High();
    	int ans=-INF;
    	for(int i=1;i<=n;i++)ans=max(ans,dis_High[i]-dis_Low[i]);
    	printf("%d
    ",ans);
    	return 0;
    }
  • 相关阅读:
    Informix IDS 11零碎规画(918考试)认证指南,第 7 部分: IDS复制(15)
    Informix IDS 11琐屑管理(918考试)认证指南,第 7 局部: IDS复制(10)
    近期招聘
    Classes 单元下的公用函数目录
    Graphics 单元下的公用函数目录
    CnPack 使用的组件命名约定
    Windows 单元下的公用函数目录(RZ_)
    Variants 单元下的公用函数目录
    StrUtils 单元下的公用函数目录
    Math 单元下的公用函数目录
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680638.html
Copyright © 2020-2023  润新知