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

题意:

  • 在一张节点有权的图上找出一条从1到N的路径,使路径上的两点A , B的差值权最大(两个点互相经过)。

题解:

  • 考虑将这张图中双向路看成两条方向相反的单向道路,并把这张图看成有向图。
  • 建立一张反图,从1->N和N->1分别跑最短路,求出每个点能经过的最小权与最大权。
  • 最后枚举每个结点,更新出点的最小权与最大权的最大差值即可。

代码片:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <queue>
  6 #define Inf 0x7fffff
  7 const int Maxx = 500000;
  8
  9 using namespace std;
 10
 11 int Head[2*Maxx+1] , Next[2*Maxx+1] , Value[Maxx+1];
 12 int Heads[2*Maxx+1] , Nexts[2*Maxx+1];
 13 int F[Maxx+1] , D[Maxx+1] , T1[Maxx+1] , T2[Maxx+1];
 14 int N , M , Sum = 0 , Num = 0 , X , Y , Z;
 15 struct Yuns{
 16     int X;
 17     int Y;
 18 }Ver[2*Maxx+1];
 19 struct Yunss{
 20     int X;
 21     int Y;
 22 }Vers[2*Maxx+1];
 23 priority_queue < pair<int , int> > Q1;
 24 priority_queue < pair<int , int> > Q2;
 25
 26 int Read(){
 27
 28     int x = 0;
 29     char c = getchar();
 30     while(c < ‘0‘ || c > ‘9‘) c = getchar();
 31     while(c >= ‘0‘ && c <= ‘9‘) x = x*10 + c-‘0‘ , c = getchar();
 32     return x;
 33
 34 }
 35
 36 void Add(int X , int Y){
 37     Ver[++Sum].X = X;
 38     Ver[Sum].Y = Y;
 39     Next[Sum] = Head[X];
 40     Head[X] = Sum;
 41     return;
 42 }
 43
 44 void Add_T(int X , int Y){
 45     Vers[++Num].X = X;
 46     Vers[Num].Y = Y;
 47     Nexts[Num] = Heads[X];
 48     Heads[X] = Num;
 49     return;
 50 }
 51
 52 void Dijkstra_1(){
 53     F[1] = Value[1];
 54     Q1.push(make_pair(F[1] , 1));
 55     while(Q1.size()){
 56         int Tag = Q1.top().second;
 57         Q1.pop();
 58         if (T1[Tag]) continue;
 59         T1[Tag] = 1;
 60         for (int i = Head[Tag] ; i ; i = Next[i]){
 61             int Y = Ver[i].Y;
 62             F[Y] = min(F[Tag] , Value[Y]);
 63             Q1.push(make_pair(F[Y] , Y));
 64         }
 65     }
 66     return;
 67 }
 68
 69 void Dijkstra_2(){
 70     D[N] = Value[N];
 71     Q2.push(make_pair(D[N] , N));
 72     while(Q2.size()){
 73         int Tag = Q2.top().second;
 74         Q2.pop();
 75         if (T2[Tag]) continue;
 76         T2[Tag] = 1;
 77         for (int i = Heads[Tag] ; i ; i = Nexts[i]){
 78             int Y = Vers[i].Y;
 79             D[Y] = max(D[Tag] , Value[Y]);
 80             Q2.push(make_pair(D[Y] , Y));
 81         }
 82     }
 83     return;
 84 }
 85
 86 void In_Work(){
 87
 88     cin >> N >> M;
 89     for (int i = 1 ; i <= N ; i++) Value[i] = Read();
 90     for (int i = 1 ; i <= M ; i++){
 91         X = Read() , Y = Read() , Z = Read();
 92         Add(X , Y);
 93         Add_T(Y , X);
 94         if (Z == 2) Add(Y , X) , Add_T(X , Y);
 95     }
 96
 97     for(int i = 1 ; i <= N ; i++) F[i] = Inf;
 98     for(int i = 1 ; i <= N ; i++) D[i] = Inf;
 99     Dijkstra_1();
100     Dijkstra_2();
101
102 }
103
104 void In_Out(){
105
106     int Ans = -1;
107     for(int i = 1 ; i <= N ; i++)
108         if (D[i]!=Inf && F[i]!=Inf)
109             Ans = max(Ans , D[i]-F[i]);
110     cout << Ans;
111
112 }
113 void In_File(){
114 //    freopen("dance.in" , "r" , stdin);
115 //    freopen("dance.out" , "w" , stdout);
116 }
117
118 int main(){
119
120     In_File();
121
122     In_Work();
123
124     In_Out();
125
126     return 0;
127
128 }

最优贸易

原文地址:https://www.cnblogs.com/Yuns/p/10387430.html

时间: 2024-10-16 07:47:36

[题解]「最短路,Noip2009」最优贸易的相关文章

「CH6101」最优贸易

「CH6101」最优贸易 传送门 考虑一种贪心的思想:我们要尽量买价格小的货物,并尽量高价转卖. 我们记 : \(mn[i]\) 为从点 \(1\) 走到点 \(i\) 经过的价格最小的货物的价格. \(mx[i]\) 为从点 \(i\) 走到点 \(n\) 经过的价格最大的货物的价格. 这两个东西可以跑两次 \(\text{SPFA}\) 求得. 那么对于任何一个点,如果它位于最优解对应的路径上,那么该最优值一定不会小于 \(mx[i] - mn[i]\) 那么我们就可以把每个点 \(i\)

【NOIP2009】最优贸易

Description C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息之后,便决定在

[NOIP2009][LuoguP1073] 最优贸易 - Tarjan,拓扑+DP

Description&Data 题面:https://www.luogu.org/problemnew/show/P1073 Solution Tarjan对联通块缩点,在DAG上按照拓扑序更新最低买入价,到每个点时再更新一下答案,即联通块内最大卖出价减去沿途的最低价格,复杂度O(n). 看机房其他人有写双向SPFA,代码短一些,反向建一张图,一遍跑最大一遍跑最小,最后枚举一下最优答案即可 Tarjan代码如下:(SPFA在后面) #include<iostream> #includ

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

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

[NOIP2009提高组]最优贸易 tarjan题解

今天刚刚学会了用tarjan写缩点(以前用两遍dfs写的),此题调了我很久,需要考虑的情况有些多,但是做出来还是挺开心的. 首先通过tarjan缩点,之后要干的事情就是计算答案. 答案有两种情况,一是在一个联通块中买进卖出,二是在一个联通块中买入,但在另外一个联通块中卖出.但是需要注意的是,以上两种情况中的联通块需要满足起点可以到达它,它也可以到达终点,并且不在一个联通块中时,买进必在卖出前. 代码中的dp(x)记录的是从起点到现在买进价最低的,每次只要用当前最大价钱减去这个值,再去和ans做比

loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分

$ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinobu 早有准备,Alice.Ayaya.Karen.Shinobu.Yoko 五人又能继续愉快地玩耍啦! 「噢--!不是有放上天的烟花嘛!」Karen 兴奋地喊道. 「啊等等--」Yoko 惊呼.Karen 手持点燃引信的烟花,「嗯??」 Yoko 最希望见到的是排列优美的烟火,当然不会放过这个机会-

从特斯拉到计算机视觉之「图像语义分割」

作者:魏秀参链接:https://zhuanlan.zhihu.com/p/21824299来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 说起特斯拉,大家可能立马会想到今年5月份发生在特斯拉Model S自动驾驶上的一宗夺命车祸.初步的调查表明,在强烈的日照条件下,驾驶员和自动驾驶系统都未能注意到牵引式挂车的白色车身,因此未能及时启动刹车系统.而由于牵引式挂车正在横穿公路,且车身较高,这一特殊情况导致Model S从挂车底部通过时,其前挡风玻璃与挂车底部发生撞击

LibreOJ #525. 「LibreOJ β Round #4」多项式

二次联通门 : LibreOJ #525. 「LibreOJ β Round #4」多项式 官方题解 : /* LibreOJ #525. 「LibreOJ β Round #4」多项式 由于会有多种解 所以只需要找出一组特殊解即可 */ #include <cstdio> #include <iostream> void read (int &now) { register char c = getchar (); for (now = 0; !isdigit (c);

LiberOJ 6003. 「网络流 24 题」魔术球 贪心或者最小路径覆盖

6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在