/*
    題意:一棵樹上,每個節點有cnt[i]個人  每條邊有權值
           現要求一個點,使得其他點到該點的所有代價最小
           代價即 ∑人數*經過邊的權值

    tree dp 自底向上 自頂向下更新2次即可

    先dfs1求得:
    ans[u]  以u為根的子樹,所有點到u的代價
    sum[u]  u及其子樹所有節點的人數
    同時記錄父邊的權值preE[u]

    再dfs2來更新得到正確的ans[u](即整棵樹以u為目標節點的代價)
    即:ans[u]=ans[p]-sum[u]*preE[u]+(tot-sum[u])*preE[u];
    這時ans[p]保存的是所有點到p的代價,當然包括從u的及其子樹到p的代價,所以要減去
    +除u的子樹外的所有節點到達u的代價

    跟hdu 2196  poj 3585  CII 4614 一樣,2次dfs
*/

#include
<cstdio>
#include
<cstring>
#include
<algorithm>
#include
<vector>

using namespace std;

const int MAXN = 100010;

vector
<pair<int,int> >G[MAXN];

long long ans[MAXN],sum[MAXN];
long long tot;
int preE[MAXN],cnt[MAXN];

void dfs1(int u,int p)
{
    sum[u]
=cnt[u];
    ans[u]
=0;
    
for(int i=0,size=G[u].size();i<size;i++)
    
{
        
int v=G[u][i].first,c=G[u][i].second;
        
if(v==p)continue;
        dfs1(v,u);
        preE[v]
=c;
        sum[u]
+=sum[v];
        ans[u]
+=(ans[v]+sum[v]*c);
    }

}

void dfs2(int u,int p)
{
    
if(u!=1)
    
{
        ans[u]
=ans[p]-sum[u]*preE[u]+(tot-sum[u])*preE[u];
    }

    
for(int i=0,size=G[u].size();i<size;i++)
    
{
        
int v=G[u][i].first;
        
if(v==p)continue;
        dfs2(v,u);
    }

}

int main()
{

    
int n;
    
int a,b,c;
    
while(~scanf("%d",&n))
    
{
        tot
=0;
        
for(int i=1;i<=n;i++)
        
{
            G[i].clear();
            scanf(
"%d",&cnt[i]);
            tot
+=cnt[i];
        }

        
for(int i=1;i<n;i++)
        
{
            scanf(
"%d%d%d",&a,&b,&c);
            G[a].push_back(make_pair(b,c));
            G[b].push_back(make_pair(a,c));
        }

        preE[
1]=0;
        dfs1(
1,0);
        dfs2(
1,0);
        printf(
"%lld\n",*min_element(ans+1,ans+1+n));
    }

    
return 0;
}