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

<!--more-->
> **题面传送门:[「最短路,Noip2009」最优贸易](http://59.61.214.20:3000/problem/show/1417 "「最短路,Noip2009」最优贸易")**

$$\varnothing$$
### **题意:**
- 在一张节点有权的图上找出一条从1到N的路径,使路径上的两点A , B的差值权最大(两个点互相经过)。

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


### **代码片:**

```cpp
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define Inf 0x7fffff
const int Maxx = 500000;

using namespace std;

int Head[2*Maxx+1] , Next[2*Maxx+1] , Value[Maxx+1];
int Heads[2*Maxx+1] , Nexts[2*Maxx+1];
int F[Maxx+1] , D[Maxx+1] , T1[Maxx+1] , T2[Maxx+1];
int N , M , Sum = 0 , Num = 0 , X , Y , Z;
struct Yuns{
int X;
int Y;
}Ver[2*Maxx+1];
struct Yunss{
int X;
int Y;
}Vers[2*Maxx+1];
priority_queue < pair<int , int> > Q1;
priority_queue < pair<int , int> > Q2;

int Read(){

int x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x*10 + c-'0' , c = getchar();
return x;

}

void Add(int X , int Y){
Ver[++Sum].X = X;
Ver[Sum].Y = Y;
Next[Sum] = Head[X];
Head[X] = Sum;
return;
}

void Add_T(int X , int Y){
Vers[++Num].X = X;
Vers[Num].Y = Y;
Nexts[Num] = Heads[X];
Heads[X] = Num;
return;
}

void Dijkstra_1(){
F[1] = Value[1];
Q1.push(make_pair(F[1] , 1));
while(Q1.size()){
int Tag = Q1.top().second;
Q1.pop();
if (T1[Tag]) continue;
T1[Tag] = 1;
for (int i = Head[Tag] ; i ; i = Next[i]){
int Y = Ver[i].Y;
F[Y] = min(F[Tag] , Value[Y]);
Q1.push(make_pair(F[Y] , Y));
}
}
return;
}

void Dijkstra_2(){
D[N] = Value[N];
Q2.push(make_pair(D[N] , N));
while(Q2.size()){
int Tag = Q2.top().second;
Q2.pop();
if (T2[Tag]) continue;
T2[Tag] = 1;
for (int i = Heads[Tag] ; i ; i = Nexts[i]){
int Y = Vers[i].Y;
D[Y] = max(D[Tag] , Value[Y]);
Q2.push(make_pair(D[Y] , Y));
}
}
return;
}

void In_Work(){

cin >> N >> M;
for (int i = 1 ; i <= N ; i++) Value[i] = Read();
for (int i = 1 ; i <= M ; i++){
X = Read() , Y = Read() , Z = Read();
Add(X , Y);
Add_T(Y , X);
if (Z == 2) Add(Y , X) , Add_T(X , Y);
}

for(int i = 1 ; i <= N ; i++) F[i] = Inf;
for(int i = 1 ; i <= N ; i++) D[i] = Inf;
Dijkstra_1();
Dijkstra_2();

}

void In_Out(){

int Ans = -1;
for(int i = 1 ; i <= N ; i++)
if (D[i]!=Inf && F[i]!=Inf)
Ans = max(Ans , D[i]-F[i]);
cout << Ans;

}
void In_File(){
// freopen("dance.in" , "r" , stdin);
// freopen("dance.out" , "w" , stdout);
}

int main(){

In_File();

In_Work();

In_Out();

return 0;

}
```

猜你喜欢

转载自www.cnblogs.com/Yuns/p/9939321.html
今日推荐