/**/ /*
    题意:一棵树上,每个节点有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;
}