首先,对 $s,t$ 各跑出单源最短路,然后考虑枚举修改点点 $i$,那么就需要对于路径 $s\to i\to t$ 求值。
枚举 $i$ 的相邻点 $u,v$,那么不难证明要把 $h_i$ 设置为 $\frac12(h_u+h_v)$,那么答案就是

\[dis_{s\to u}+2\left(\frac12(h_u-h_v)\right)^2+dis_{t\to v}\]

展开括号

\[dis_{s\to u}+dis_{t\to v}+\frac12h_u^2+\frac12h_v^2-h_uh_v\]

我们不能对每个点所有的相邻点进行枚举,会被菊花卡到超时,考虑快速找点对。
发现这是一条线段,可以使用李超树来维护。其中线段的斜率是 $-h_u$,截距是 $dis_{s\to u}+\frac12h_u^2$,查询就是找 $x=h_v$ 时的最大值,然后再加上 $dis_{t\to v}+\frac12h_v^2$。

但是,如果我们对斜率 $h$ 进行排序,会发现这是凸壳求 $\max$,并且不在线,可以使用整体二分。

注意:使用整体二分求凸壳 $\max$ 时,实际上相当于钦定了先来的点是 $u$ 后来的点是 $v$,所以贡献就是 $dis_{s\to u}+dis_{t\to v}$ 而不是 $\min(dis_{s\to u}+dis_{t\to v},dis_{s\to v}+dis_{t\to u})$,取 $\min$ 会破坏凸壳导致 WA。
另外,需要特判 $u,v$ 被修改的情况。
另外,最后不能直接把答案除以二,会掉精度,

#include<bits/stdc++.h>
#define siz(x) int((x).size())
#define all(x) std::begin(x),std::end(x)
#define fi first
#define se second
using namespace std;
using unt=unsigned;
using loli=long long;
using lolu=unsigned long long;
using pii=pair<int,int>;
using pli=pair<loli,int>;
mt19937_64 rng(random_device{}());
constexpr int N=1e5+7;
constexpr loli inf=1e18;
int n,m,s1,s2;
int h[N],vis[N];
loli d[2][N],ans=inf;
basic_string<int>g[N];
priority_queue<pli>q;
loli sqr(int x){return 1ll*x*x;}
void dijk1(int s,loli *dis){
	memset(vis+1,0,sizeof(int)*n);
	for(int i=1;i<=n;i++)dis[i]=inf;
	q.emplace(dis[s]=0,s);
	while(!q.empty()){
		int u=q.top().se;q.pop();
		if(vis[u])continue;else vis[u]=1;
		for(int v:g[u]){
			loli w=sqr(h[u]-h[v]);
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				if(!vis[v])q.emplace(-dis[v],v);
			}
		}
	}
}
void dijk2(int s,loli *dis){
	memset(vis+1,0,sizeof(int)*n);
	for(int i=1;i<=n;i++)dis[i]=inf;
	q.emplace(dis[s]=0,s);
	for(int v:g[s])q.emplace(dis[v]=0,v);
	while(!q.empty()){
		int u=q.top().se;q.pop();
		if(vis[u])continue;else vis[u]=1;
		for(int v:g[u]){
			loli w=sqr(h[u]-h[v]);
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				if(!vis[v])q.emplace(-dis[v],v);
			}
		}
	}
}
#define mid ((l+r)>>1)
void solve(int u,int l,int r,int x,int y){
	if(l>r)return;
	int pos=-1;loli tmp=8*inf;
	for(int k=x;k<=y;k++){
		int p=g[u][mid],q=g[u][k];
		loli sum=2*(d[0][p]+d[1][q])+sqr(h[p])+sqr(h[q])-2ll*h[p]*h[q];
		if(tmp>sum)tmp=sum,pos=k;
	}
	ans=min(ans,tmp);
	solve(u,l,mid-1,x,pos);
	solve(u,mid+1,r,pos,y);
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ios::sync_with_stdio(false);cin.tie(nullptr);
	cin>>n>>m>>s1>>s2;
	for(int i=1;i<=n;i++)cin>>h[i];
	for(int i=1,u,v;i<=m;i++)cin>>u>>v,g[u]+=v,g[v]+=u;
	dijk2(s1,d[0]);ans=min(ans,2*d[0][s2]);
	dijk2(s2,d[1]);ans=min(ans,2*d[1][s1]);
	dijk1(s1,d[0]);
	dijk1(s2,d[1]);
	for(int i=1;i<=n;i++){
		sort(all(g[i]),[](int x,int y){
			return h[x]<h[y];
		});
		solve(i,0,siz(g[i])-1,0,siz(g[i])-1);
	}
	cout<<ans/2;
	if(ans&1)cout<<".5";
	return 0;
}