#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define int long long
using namespace std;
inline int gi(){char tmp=getchar();int ans=0;while(!isdigit(tmp))tmp=getchar();while(isdigit(tmp)){ans=ans*10+tmp-'0';tmp=getchar();}return ans;}
int n;
const int N = 1020000;
struct Edg{int v,w,nxt;}Edge[N<<1];int Head[N];
inline void Add(int u,int v,int w){static int cnt=0;Edge[++cnt].v=v;Edge[cnt].nxt=Head[u];Head[u]=cnt;Edge[cnt].w=w;}
struct Nod{
int pos,dis;
bool operator > (const Nod &x)const{
return dis > x.dis;
}
};
int Dis[N],Vis[N];
priority_queue<Nod,vector<Nod>,greater<Nod> > Q;
inline void Pu(int pos,int dis){
Nod p;p.pos=pos;p.dis=dis;
Q.push(p);
}
int Ans[N];
void Dij(){
while(!Q.empty()){
int pos=Q.top().pos;Q.pop();
if(Vis[pos]) continue;
// Ans[pos] = Ans[pos] - (Ans[pos]>>1ll);
Vis[pos] = 1;
for(int i=Head[pos];i;i=Edge[i].nxt){
int arr = Edge[i].v,w=Edge[i].w;
if(Vis[arr]==0)continue;
if(Dis[pos] + Dis[arr] == Dis[w]){
Ans[w] += Ans[pos] * Ans[arr];
}
if(Dis[pos] + Dis[arr] < Dis[w]){
Ans[w] = Ans[pos] * Ans[arr];
Dis[w] = Dis[pos] + Dis[arr];
Pu(w,Dis[w]);
}
}
}
}
signed main()
{
#ifdef TSUKIAKIOI
freopen("data.in","r",stdin);
#endif
int n=gi();
for(int i=1;i<=n;++i) {Dis[i]=gi();Pu(i,Dis[i]);Ans[i]=1;}
int a,b,c;
while(~scanf("%lld%lld%lld",&a,&b,&c)){
a++,b++,c++;
Add(a,b,c);
if(a==b) continue;
Add(b,a,c);
}
Dij();
printf("%lld %lld",Dis[1],Ans[1]);
return 0;
}