感觉是非常浪费时间的一道题
直接 O ( n 2 ) O(n^2) O(n2)枚举上下界去跑最短路就行了…
也可以枚举下界,二分上界可能可以加速一下
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
const int inf = 2e9+1;
struct edge{
int to,nxt,w;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int w)
{
d[++cnt] = (edge){v,head[u],w},head[u] = cnt;
}
int dis[maxn],h[maxn],a[maxn],n,m,vis[maxn];
typedef pair<int,int>p;
bool dijstra(int l,int r)
{
for(int i=1;i<=n;i++) dis[i] = inf, vis[i] = 0;
priority_queue<p,vector<p>,greater<p> >q; q.push( p(0,1) );
dis[1] = 0;
while( !q.empty() )
{
int u = q.top().second; q.pop();
if( vis[u] ) continue;
vis[u] = 1;
for(int i=head[u];i;i=d[i].nxt )
{
int v = d[i].to;
if( h[v]<l||h[v]>r ) continue;
if( dis[v]>dis[u]+d[i].w )
{
dis[v] = dis[u]+d[i].w;
q.push( p(dis[v],v) );
}
}
}
return dis[n]!=inf;
}
int main()
{
int T; cin >> T;
while( T-- )
{
cin >> n >> m;
for(int i=1;i<=n;i++)
scanf("%d",&h[i] ),a[i]=h[i];
for(int i=1;i<=m;i++)
{
int l,r,w; scanf("%d%d%d",&l,&r,&w);
add(l,r,w); add(r,l,w);
}
sort( a+1,a+1+n );
int H = inf,ans = inf;
for(int i=1;i<=n;i++)//枚举下界
for(int j=i;j<=n;j++)//枚举上界
{
if( h[1]<a[i] || h[1]>a[j] ) continue;
if( dijstra(a[i],a[j]) )
{
if( a[j]-a[i]<H ) ans = dis[n], H = a[j]-a[i];
}
}
cout << H << " " << ans << endl;
cnt = 1;
for(int i=1;i<=n;i++) head[i] = 0;
}
}