列表

详情


NC50379. 最优贸易

描述

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

假设1~n号城市的水晶球价格分别为4,3,5,6,1。
阿龙可以选择如下一条线路:,并在2号城市以3的价格买入水晶球,在3号城市以5的价格卖出水晶球,赚取的旅费数为2。
阿龙也可以选择如下一条线路,并在第1次到达5号城市时以1的价格买入水晶球,在第2次到达4号城市时以6的价格卖出水晶球,赚取的旅费数为5。
现在给出n个城市的水晶球价格,m条道路的信息(每条道路所连接的两个城市的编号以及该条道路的通行情况)。请你告诉阿龙,他最多能赚取多少旅费。

输入描述

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

输出描述

输出共1行,包含1个整数,表示最多能赚取的旅费。如果没有进行贸易,则输出0。

示例1

输入:

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

输出:

5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 135ms, 内存消耗: 2792K, 提交时间: 2019-12-28 21:54:19

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+1;
int n, m;
int price[MAXN];
vector<pair<int, int>> edges;
vector<int> reached;

int gao(int S) {
  vector<int> d(n+1, 0x3f3f3f3f);
  d[S] = price[S];
  int ans = 0;
  for (int i = 0; i < n; i++) {
    bool ok = true;
    for (auto it: edges) {
      int x = it.first, y = it.second;
      if (d[y] > d[x]) d[y] = d[x], ok = false;;
      if (d[x] != 0x3f3f3f3f && d[y] > price[y]) d[y] = price[y], ok = false;
      if (S == 1 && reached[y] != 0x3f3f3f3f) ans = max(ans, price[y] - d[y]);
    }
    if (ok) break;
  }
  if (S == n) reached = d;
  return ans;
}
int main() {
  cin >> n >> m;
  for (int i = 1; i <= n; i++) cin >> price[i];
  while (m--) {
    int x, y, z; cin >> x >> y >> z;
    edges.push_back({x, y});
    if (z == 2) edges.push_back({y, x});
  }

  for (auto &it: edges) swap(it.first, it.second);
  gao(n);
  for (auto &it: edges) swap(it.first, it.second);
  cout << gao(1) << endl;
}

C++(g++ 7.5.0) 解法, 执行用时: 68ms, 内存消耗: 7244K, 提交时间: 2023-04-17 17:18:44

#include<bits/stdc++.h>
#define N 100005
#define int long long
using namespace std;
vector<int> d[N];
int n,m,f[N],res[N],cost[N];
void dfs(int now,int mini,int fa){
    bool flag=1;
    mini=min(cost[now],mini);
    if(res[now]>mini){
        res[now]=mini;
        flag=0;
    }
    int maxi=max(f[fa],cost[now]-mini);
    if(f[now]<maxi){
        f[now]=maxi;
        flag=0;
    }
    if(flag){
        return;
    }
    for(int i=0;i<d[now].size();i++){
        dfs(d[now][i],mini,now);
    }
}
signed main(){
    cin.tie(0)->sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>cost[i];
    }
    for(int i=1;i<=m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        if(z==1){
            d[x].push_back(y);
        }
        else{
            d[x].push_back(y);
            d[y].push_back(x);
        }
    }
    memset(res,0x3f,sizeof(res));
    dfs(1,0x3f3f3f3f,0);
    cout<<f[n]<<endl;
}

C++ 解法, 执行用时: 50ms, 内存消耗: 5840K, 提交时间: 2022-06-19 19:38:07

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
vector<int>G[N];
int n,m,f[N],g[N],a[N];
inline void dfs(int x,int v,int p)
{
	bool fl=1;
	v=min(a[x],v);
	if(g[x]>v)
	{
		g[x]=v;
		fl=0;
	}
	int c=max(f[p],a[x]-v);
	if(f[x]<c)
	f[x]=c,fl=0;
	if(fl)return ;
	for(int i=0;i<G[x].size();i++)
	dfs(G[x][i],v,x);
}
int main(){
	scanf("%d%d",&n,&m);
	memset(g,0x3f3f3f3f,sizeof(g));
	for(int i=1; i<=n; i++)
	scanf("%d",&a[i]);
	while(m--)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		G[x].push_back(y);
		if(z==2)
		G[y].push_back(x);
	}
	dfs(1,1e9,0);
	cout<<f[n]<<endl;
	return 0;
}

上一题