1. 程式人生 > >[題解]「最短路,Noip2009」最優貿易

[題解]「最短路,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;

}
```