「CH6101」最优贸易

「CH6101」最优贸易

传送门
考虑一种贪心的思想:我们要尽量买价格小的货物,并尽量高价转卖。
我们记 :

  • \(mn[i]\) 为从点 \(1\) 走到点 \(i\) 经过的价格最小的货物的价格。
  • \(mx[i]\) 为从点 \(i\) 走到点 \(n\) 经过的价格最大的货物的价格。

这两个东西可以跑两次 \(\text{SPFA}\) 求得。
那么对于任何一个点,如果它位于最优解对应的路径上,那么该最优值一定不会小于 \(mx[i] - mn[i]\)
那么我们就可以把每个点 \(i\) 的 \(mx[i] - mn[i]\) 取最大值,就一定可以取到最优答案。
参考代码:

#include <cstring>
#include <cstdio>
#include <queue>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while ('0' > c || c > '9') f |= c == '-', c = getchar();
    while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
    s = f ? -s : s;
}

const int _ = 1e5 + 5, __ = 5e5 + 5;

int tot, head1[_], head2[_], nxt[__ << 2], ver[__ << 2];
inline void Add_edge(int* head, int u, int v)
{ nxt[++tot] = head[u], head[u] = tot, ver[tot] = v; }

int n, m, val[_], mn[_], mx[_], exi[_];

inline void spfa1() {
    static queue < int > Q;
    while (!Q.empty()) Q.pop();
    memset(exi + 1, 0, sizeof (int) * n);
    memset(mn + 1, 0x3f, sizeof (int) * n);
    Q.push(1), mn[1] = val[1], exi[1] = 1;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop(), exi[u] = 0;
        for (rg int i = head1[u]; i; i = nxt[i]) {
            int v = ver[i];
            if (mn[v] > min(mn[u], val[v])) {
                mn[v] = min(mn[u], val[v]);
                if (!exi[v]) exi[v] = 1, Q.push(v);
            }
        }
    }
}

inline void spfa2() {
    static queue < int > Q;
    while (!Q.empty()) Q.pop();
    memset(exi + 1, 0, sizeof (int) * n);
    memset(mx + 1, 0, sizeof (int) * n);
    Q.push(n), mx[n] = val[n], exi[n] = 1;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop(), exi[u] = 0;
        for (rg int i = head2[u]; i; i = nxt[i]) {
            int v = ver[i];
            if (mx[v] < max(mx[u], val[v])) {
                mx[v] = max(mx[u], val[v]);
                if (!exi[v]) exi[v] = 1, Q.push(v);
            }
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
    file("cpp");
#endif
    read(n), read(m);
    for (rg int i = 1; i <= n; ++i) read(val[i]);
    for (rg int u, v, x; m--; ) {
        read(u), read(v), read(x);
        Add_edge(head1, u, v), Add_edge(head2, v, u);
        if (x == 2) Add_edge(head1, v, u), Add_edge(head2, u, v);
    }
    spfa1(), spfa2();
    int ans = 0;
    for (rg int i = 1; i <= n; ++i) ans = max(ans, mx[i] - mn[i]);
    printf("%d\n", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/zsbzsb/p/12190206.html

时间: 2024-08-30 13:36:47

「CH6101」最优贸易的相关文章

[题解]「最短路,Noip2009」最优贸易

题意: 在一张节点有权的图上找出一条从1到N的路径,使路径上的两点A , B的差值权最大(两个点互相经过). 题解: 考虑将这张图中双向路看成两条方向相反的单向道路,并把这张图看成有向图. 建立一张反图,从1->N和N->1分别跑最短路,求出每个点能经过的最小权与最大权. 最后枚举每个结点,更新出点的最小权与最大权的最大差值即可. 代码片: 1 #include <iostream> 2 #include <cstdio> 3 #include <algorith

「标准」的 JS风格

「标准」的 JS风格 2016-10-31 10:09 by 聂微东, 2099 阅读, 21 评论, 收藏, 编辑 首先,这份 JS风格指南已经在我司的前端团队实行半年多了: 其次,在程序员的世界里,从入行到资深都需要面对几个世界级的难题,如: 世界上最好的编辑器是什么? 是用空格还是 TAB?用空格还特么衍生出 2空格 VS 4空格. JS到底要不要写分号? ... 最后,PHP是世界上最好的语言. 一.规范VS自由 对程序员的每个个体来说,有代码规范其实不一定是好事,因为肯定会影响到写码的

「SCOI2014」方伯伯的商场之旅

「SCOI2014」方伯伯的商场之旅 题目描述 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 \(i\) 的人面前的第 \(j\) 堆的石子的数量,刚好是 \(i\) 写成 \(K\) 进制后的第 \(j\) 位. 现在方伯伯要玩一个游戏,商场会给方伯伯两个整数 \(L,R\).方伯伯要把位置在 \([L, R]\) 中的每个人的石子都合并成一堆石子.每次操作,他可以选择一个人面前的两堆石子,将其中的一堆中的某些石子移动到另一堆,代价

「oTMS」完成C1轮战略融资,从技术工具到“技术+服务”

近日,互联网+运输管理平台「oTMS」宣布获得招商局创投C1轮战略投资,青桐资本担任独家FA.此前,oTMS曾获得紫辉创投.经纬中国.百度.成为资本.陈伟星等多家机构和投资人的投资.据了解,本轮融资将用于继续推进"SaaS TMS+运输控制塔(技术+服务)"战略. oTMS成立于2013年,以货主需求为业务逻辑出发点,其主营产品是基于云的TMS(运输管理系统),主要面向大型生产/商贸企业(服装.零售.消费品等)和大型3PL(第三方物流),通过SaaS平台(PC+移动APP)连接货主.第

「题解」「美团 CodeM 资格赛」跳格子

目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞定,最后无奈 \(90pts\) . 然而 \(T2\) 想到很多很奇怪的做法,结果正解在 \(28min\) 之内做出... 结果 \(T3\) 是本人最不擅长的伪期望,直接跳过,啥都没得. 来水一发 \(T1\) 的题解... 题目描述 点这里 考场思路 其实并没有什么十分特别的思路,就是一通乱

「JSOI2011」汇总

「JSOI2011」柠檬 斜率优化题. 在优化前,还有一个值得一提的优化: 对于最后的最有分割方案,每一段的两个端点一定是同颜色的,并且作为这一段的 \(s_0\) 证明:如果不作为这一段的 \(s_0\),那么它显然没有贡献,把这一个单独分出来显然更优,直到最后两个端点就一定都是 \(s_0\) ,颜色相同. 那么我们只需要从之前和该点种类相同的位置进行转移即可. 这样就从直接枚举的复杂度 \(O(n^3)\) 优化到了 \(O(n^2)\) ,但还是不够,继续考虑优化. 我们先把转移方程写出

「SCOI2012」喵星球上的点名

「SCOI2012」喵星球上的点名 填一个很久以前用 \(\texttt{AC}\) 自动机没填上的坑. 关于本题,能够通过本题的算法很多,这里作者采用的是后缀数组+树状数组的做法. 首先有一个显然的结论:若 \(s_2\) 是 \(s_1\) 的子串,则 \(s_1\) 一定存在一个后缀与 \(s_2\) 的最长公共前缀为 \(|s_2|\). 我们将读入的姓.名.询问串连成一个整体,形成一个字符串 \(s\),且在每一个姓.名.询问串中插入一个不存在文本中的字符,且保证询问串后插入的比姓名串

「JSOI2015」salesman

「JSOI2015」salesman 传送门 显然我们为了使收益最大化就直接从子树中选大的就好了. 到达次数的限制就是限制了可以选的子树的数量,因为每次回溯上来都会减一次到达次数. 多种方案的判断就是看自己选中的子树中和没选的子树中是否存在两个值相等的,这样它们就可以通过互换来达到另一种方案,值得注意的是如果选了一个值为 \(0\) 的子树就肯定可以多一种方案出来,因为这颗子树选或不选都是满足最优的. 这里有个小问题:交到BZOJ上面去它会提示你 sort 没有声明,此时需要 #include

AC日记——「HNOI2017」单旋 LiBreOJ 2018

#2018. 「HNOI2017」单旋 思路: set+线段树: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxtree maxn<<2 int val[maxtree],tag[maxtree],L[maxtree],R[maxtree],mid[maxtree]; int op[maxn],ki[maxn],bi[maxn],cnt,size,n,ch[maxn]