题目链接:http://nyoj.top/web/contest/problem/cid/7/num/E
思路: 题目要求1出发,到n结束。我们用第一次用bfs从1到n跑正向图求一下经过点的最小权值,第二次用bfs从n到1跑反向图求一下经过点的最大权值,然后求出经过每一个点的最大权值和最小权值之差,最大的既是答案。
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define GT() int T;scanf("%d",&T);while(T--)
const int maxn = 5e5+7;
int n,m;
int min_dis[maxn], max_dis[maxn], min_vis[maxn], max_vis[maxn];
int s, t;
vector<pair<int,int> >E[maxn], G[maxn];
int cnt1, cnt2;
void init()
{
memset(min_vis,0,sizeof(min_vis));
memset(max_vis,0,sizeof(max_vis));
for(int i = 0; i <= n + 1; i++)
E[i].clear();
}
void min_bfs()
{
min_vis[s] = 1;
queue <int> Q;
Q.push(s);
while(!Q.empty())
{
int now = Q.front();
Q.pop();
for(int j = 0; j < E[now].size(); j++)
{
int v = E[now][j].first;
min_dis[v] = min(min_dis[v], min_dis[now]);
if(min_vis[v]) continue;
min_vis[v] = 1;
Q.push(v);
}
}
}
void max_bfs()
{
max_vis[t] = 1;
queue <int> Q;
Q.push(t);
while(!Q.empty())
{
int now = Q.front();
Q.pop();
for(int j = 0; j < G[now].size(); j++)
{
int v = G[now][j].first;
max_dis[v] = max(max_dis[v], max_dis[now]);
if(max_vis[v]) continue;
max_vis[v] = 1;
Q.push(v);
}
}
}
int main()
{
while(~scanf("%d%d", &n,&m))
{
init();
for(int i = 1; i <= n; i++)
{
scanf("%d", &min_dis[i]);
max_dis[i] = min_dis[i];
}
int a, b, x;
for(int i = 0; i < m; i++)
{
scanf("%d%d%d",&a, &b, &x);
E[a].push_back({b, 0});
G[b].push_back({a, 0});
if(x == 2)
{
E[b].push_back({a, 0});
G[a].push_back({b, 0});
}
}
s = 1, t = n;
min_bfs(); max_bfs();
int ans = 0;
for(int i = 1; i <= n; i++)
if(min_vis[i] && max_vis[i])
ans = max(ans, max_dis[i] - min_dis[i]);
printf("%d\n", ans);
}
return 0;
}
/*
5 5
4 3 5 6 1
1 2 1
1 4 1
2 3 2
3 5 1
4 5 2
*/