• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
最优贸易-SPFA+思维

最优贸易

最贸易

思路

​ 设我们可以以\(i\)为分界点,分别求经过\([1, i]\)的路径的最低价格,和\([i, n]\)的最高价格, 相减便可以得到以以\(i\)为分解点的最短路径,这样遍历所有分解点可以得到答案, 对于上述做法左右两边都是可以任意走的,也可以当天买当天卖, 那么可以用dp来求吗,显然图中可能存在环路,所以dp的方法不可行,那么我们可以考虑Dijkstra或SPFA, 对于Dijkstra显然也是不可行的,因为贪心解可能不是正解。

​ 如下, 4号点更新后不会在被更新,所以我们考虑使用SPFA。

image-20230413102845078

​ SPFA的话肯定遍历\(n - 1\)条边, 那么保证了途中会经过n个点,那么我们寸图的时候记录一个反向边, 然后开两个数组求最优值即可。 平均复杂度\(O(M)\)

Code

#include <iostream>
#include <cstring>
#include <queue>

using i64 = long long;

const int N = 1e5 + 10, M = 1e6 + 10;

int n, m;

int hs[N], ht[N], e[M], ne[M], w[N], idx;

int dmin[N], dmax[N];

bool st[N];

void add(int h[], int a, int b) {
	ne[idx] = h[a], h[a] = idx, e[idx ++] = b;
}

void spfa(int h[], int dist[], int type) {
	std::queue<int> q1;

	if (type) {
		memset(dist, -0x3f, sizeof dmax);
		dist[n] = w[n];
		q1.push(n);
	} else {
		memset(dist, 0x3f, sizeof dmin);
		dist[1] = w[1];
		q1.push(1);
	}

	while (q1.size()) {
		int t = q1.front(); q1.pop();
		
		st[t] = false;

		// std::cout << t << "\n";

		for (int i = h[t]; ~i; i = ne[i]) {
			int j = e[i];

			if (type == 1 && dist[j] < std::max(w[j], dist[t])) {
				dist[j] = std::max(w[j], dist[t]);
				q1.push(j);
				if (!st[j]) st[j] = true;
			} else if (type == 0 && dist[j] > std::min(w[j], dist[t])) {
				dist[j] = std::min(w[j], dist[t]);
				q1.push(j);
				if (!st[j]) st[j] = true;
			}
		}
	}
}

int main() {
	memset(hs, -1, sizeof hs);
	memset(ht, -1, sizeof ht);

	std::cin >> n >> m;

	for (int i = 1; i <= n; i ++) std::cin >> w[i];

	for (int i = 1; i <= m; i ++) {
		int x, y, z;

		std::cin >> x >> y >> z;

		add(hs, x, y), add(ht, y, x);

		if (z == 2) add(hs, y, x), add(ht, x, y);
	}

	spfa(hs, dmin, 0);

	spfa(ht, dmax, 1);

	int res = 0;

	for (int i = 1; i <= n; i ++) {
		res = std::max(res, dmax[i] - dmin[i]);
	}

	std::cout << res;
}
posted on 2023-04-13 10:34  Jack404  阅读(34)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3