洛谷P1073 最优贸易
建模。本题是让我们在一张图上找到一条从1到N的道路,使路径上能选出两个点p, q(先p后q),且 q 的权值- p 的权值最大。
考虑用最短路算法分别算出:
1.从起点到某个点的路径上的最小的 p ;
2.从终点到某个点最大的 q。
分别记为 d1 和 d2 。
把每个节点看做两条路径相交的点。于是,枚举每个节点 x, 用 d2[ x ] - d1[ x ] 更新答案即可。
注意用最短路算法求解问题(2)时需要用到反图。
1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef pair<int, int> P;
4 const int MAXN = 100000 + 20;
5 const int MAXM = 500000 + 20;
6 const int INF = 0x3f3f3f3f;
7
8 int N, M, C[MAXN];
9
10 inline int read()
11 {
12 int x = 0; char ch = getchar();
13 while(!isdigit(ch)) ch = getchar();
14 while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
15 return x;
16 }
17
18 namespace dij
19 {
20 vector<int> g[MAXN], rg[MAXN];
21 int d1[MAXN], d2[MAXN];
22
23 void init()
24 {
25 memset(d1, 0x3f, sizeof(d1));
26 memset(d2, 0, sizeof(d2));
27 }
28
29 inline void addedge(int u, int v, int t)
30 {
31 if(t == 1)
32 {
33 g[u].push_back(v);
34 rg[v].push_back(u);
35 }
36 else
37 {
38 g[u].push_back(v);
39 g[v].push_back(u);
40 rg[u].push_back(v);
41 rg[v].push_back(u);
42 }
43 }
44
45 void dijkstra(int s)
46 {
47 priority_queue<P, vector<P>, greater<P> > q;
48 memset(d1, 0x3f, sizeof(d1));
49 d1[s] = C[s];
50 q.push(P(C[s], s));
51
52 while(!q.empty())
53 {
54 P p = q.top(); q.pop();
55 int u = p.second;
56 if(d1[u] < p.first) continue;
57
58 for(int i = 0; i < (int) g[u].size(); i++)
59 {
60 int v = g[u][i];
61 if(d1[v] > min(d1[u], C[v]))
62 {
63 d1[v] = min(d1[u], C[v]);
64 q.push(P(d1[v], v));
65 }
66 }
67 }
68 }//
69
70 void rdijkstra(int s)
71 {
72 priority_queue<P, vector<P>, less<P> > q;
73 memset(d2, 0, sizeof(d2));
74
75 d2[s] = C[s];
76 q.push(P(C[s], s));
77
78 while(!q.empty())
79 {
80 P p = q.top(); q.pop();
81 int u = p.second;
82 if(d2[u] > p.first) continue;
83
84 for(int i = 0; i < (int) rg[u].size(); i++)
85 {
86 int v = rg[u][i];
87 if(d2[v] < max(d2[u], C[v]))
88 {
89 d2[v] = max(d2[u], C[v]);
90 q.push(P(d2[v], v));
91 }
92 }
93 }
94 }
95
96 }
97
98 int main()
99 {
100 //freopen("p1073.txt", "r", stdin);
101 cin>>N>>M;
102 for(int i = 1; i <= N; i++)
103 C[i] = read();
104
105 using namespace dij;
106 int u, v;
107 for(int i = 1; i <= M; i++)
108 {
109 u = read(), v = read();
110 addedge(u, v, read());
111 }
112
113 dijkstra(1);
114 rdijkstra(N);
115
116 // for(int i = 1; i <= N; i++)
117 // cout<<d1[i]<<" "<<d2[i]<<endl;
118 // puts("");
119 int ans = -1;
120 for(int i = 1; i <= N; i++)
121 {
122 ans = max(ans, d2[i] - d1[i]);
123 // cout<<i<<" "<<d2[i] - d1[i]<<endl;
124 }
125
126 cout<<ans<<endl;
127 return 0;
128 }