传送门

感觉是非常浪费时间的一道题

直接 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;
	}
}