//反BFS找能到终点的点,正BFS找到此点及以前最小代价。正BFS实际上是SPFA,要熟练掌握重复更新的思想。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
const int maxm = 500010;
int n, m, tot, tot1, ans;
int st[maxn], rst[maxn], c[maxn], p[maxn];
bool is[maxn], vis[maxn];
struct node{
int v, nxt;
} edge[2*maxm], redge[2*maxm];
inline int read(){
int num = 0;
char c;
while((c = getchar()) == ' ' || c == '\r' || c == '\n');//?
num = c - '0';
while(isdigit(c = getchar())) num = num*10 + c - '0';
return num;
}
inline void in(int x, int y){
edge[++tot].v = y;
edge[tot].nxt = st[x];
st[x] = tot;
}
inline void rin(int x, int y){
redge[++tot1].v = y;
redge[tot1].nxt = rst[x];
rst[x] = tot1;
}
inline void isCon(){
queue<int> q;
q.push(n);
while(!q.empty()){
int now = q.front(); q.pop();
for(int i = rst[now]; i; i = redge[i].nxt){
int to = redge[i].v;
if(is[to]) continue;
is[to] = 1;
q.push(to);
}
}
}
inline void Play(){
queue<int> q;
q.push(1);
//c[1] = p[1];
while(!q.empty()){
int now = q.front(); q.pop();
vis[now] = 0;//表示在不在队列里,可重复更新!
for(int i = st[now]; i; i = edge[i].nxt){
int to = edge[i].v;
int tmp = min(c[to], min(c[now], p[now]));
if(c[to] > tmp){//要更新了再更新,等等,这不是spfa吗...
c[to] = tmp;
if(vis[to]) continue;
vis[to] = 1;
q.push(to);
}
}
}
}
int main(){
n = read();
m = read();
for(int i = 1; i <= n; i++)
p[i] = read();
for(int i = 1, x, y, z; i <= m; i++){
x = read();
y = read();
z = read();
in(x, y);
rin(y, x);
if(z == 2){
in(y, x);
rin(x, y);
}
}
/*for(int i = 1; i <= n; i++)
c[i] = p[i];*/
memset(c, 0x3f3f3f3f, sizeof(c));
isCon();
Play();
for(int i = 1; i <= n; i++)
if(is[i])
ans = max(ans, p[i] - c[i]);
printf("%d\n", ans);
return 0;
}
洛谷 1073 最优贸易
最新推荐文章于 2021-09-20 14:56:48 发布