#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
#define EACH(i, s)                                                             \\
  for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)

template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T1, class T2> ostream &operator<<(ostream &s, pair<T1, T2> P) {
  return s << '<' << P.first << ", " << P.second << '>';
}
template <class T> ostream &operator<<(ostream &s, vector<T> P) {
  for (int i = 0; i < P.size(); ++i) {
    if (i > 0) {
      s << " ";
    }
    s << P[i];
  }
  return s;
}
template <class T> ostream &operator<<(ostream &s, vector<vector<T>> P) {
  for (int i = 0; i < P.size(); ++i) {
    s << endl << P[i];
  }
  return s << endl;
}
template <class T1, class T2> ostream &operator<<(ostream &s, map<T1, T2> P) {
  EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; }
  return s << endl;
}

typedef pair<int, int> pint;
const int MAX = 210000;

const int MAX_UF = MAX;
struct UnionFind {
  int size_;
  int par[MAX_UF];
  int rank[MAX_UF];

  UnionFind(int n = 0) {
    size_ = n;
    for (int i = 0; i < n; ++i)
      par[i] = i, rank[i] = 0;
  }
  void init(int n) {
    size_ = n;
    for (int i = 0; i < n; ++i)
      par[i] = i, rank[i] = 0;
  }
  int root(int x) { return par[x] == x ? x : par[x] = root(par[x]); }
  bool same(int x, int y) { return root(x) == root(y); }

  void connect(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return;
    if (rank[x] < rank[y])
      par[x] = y;
    else {
      par[y] = x;
      if (rank[x] == rank[y])
        ++rank[x];
    }
  }

  friend ostream &operator<<(ostream &s, UnionFind uf) {
    return s << uf.group();
  }
  vector<vector<int>> group() {
    vector<vector<int>> res;
    vector<bool> fixed(size_, false);
    for (int i = 0; i < size_; ++i) {
      if (!fixed[i]) {
        vector<int> temp;
        for (int j = i; j < size_; ++j) {
          if (same(i, j))
            temp.push_back(j), fixed[j] = true;
        }
        res.push_back(temp);
      }
    }
    return res;
  }
} uf;

string str;
int a[MAX];
int b[MAX];
int N;
pint seg[MAX];

bool solve() {
  int n = str.size() + 1;

  vector<vector<int>> grs = uf.group();
  for (int i = 0; i < grs.size(); ++i) {
    int sum = 0;
    for (auto v : grs[i])
      sum += b[v];
    while (sum < 0)
      sum += 26;
    if (sum % 26 != 0)
      return false;
  }
  return true;
}

int main() {
  while (cin >> str >> N) {
    int n = str.size() + 1;
    uf.init(n);
    for (int i = 0; i < N; ++i) {
      cin >> seg[i].first >> seg[i].second;
      --seg[i].first;
      uf.connect(seg[i].first, seg[i].second);
    }
    for (int i = 0; i < n / 2; ++i) {
      int j = n - i - 1;
      uf.connect(i, j);
    }

    memset(a, 0, sizeof(a));
    for (int i = 0; i < str.size(); ++i) {
      a[i] = (int)(str[i] - 'a');
    }
    b[0] = a[0];
    for (int i = 0; i < str.size(); ++i) {
      b[i + 1] = a[i + 1] - a[i];
      if (b[i + 1] < 0)
        b[i + 1] += 26;
      // cout << i + 1 << ", " << a[i+1] << ", " << b[i+1] << endl;
    }
    // COUT(uf);

    if (solve())
      puts("YES");
    else
      puts("NO");
  }
}

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
#define EACH(i, s)                                                             \\
  for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)

template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T1, class T2> ostream &operator<<(ostream &s, pair<T1, T2> P) {
  return s << '<' << P.first << ", " << P.second << '>';
}
template <class T> ostream &operator<<(ostream &s, vector<T> P) {
  for (int i = 0; i < P.size(); ++i) {
    if (i > 0) {
      s << " ";
    }
    s << P[i];
  }
  return s;
}
template <class T> ostream &operator<<(ostream &s, vector<vector<T>> P) {
  for (int i = 0; i < P.size(); ++i) {
    s << endl << P[i];
  }
  return s << endl;
}
template <class T1, class T2> ostream &operator<<(ostream &s, map<T1, T2> P) {
  EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; }
  return s << endl;
}

typedef pair<int, int> pint;
const int MAX = 210000;

const int MAX_UF = MAX;
struct UnionFind {
  int size_;
  int par[MAX_UF];
  int rank[MAX_UF];

  UnionFind(int n = 0) {
    size_ = n;
    for (int i = 0; i < n; ++i)
      par[i] = i, rank[i] = 0;
  }
  void init(int n) {
    size_ = n;
    for (int i = 0; i < n; ++i)
      par[i] = i, rank[i] = 0;
  }
  int root(int x) { return par[x] == x ? x : par[x] = root(par[x]); }
  bool same(int x, int y) { return root(x) == root(y); }

  void connect(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return;
    if (rank[x] < rank[y])
      par[x] = y;
    else {
      par[y] = x;
      if (rank[x] == rank[y])
        ++rank[x];
    }
  }

  friend ostream &operator<<(ostream &s, UnionFind uf) {
    return s << uf.group();
  }
  vector<vector<int>> group() {
    vector<vector<int>> res;
    vector<bool> fixed(size_, false);
    for (int i = 0; i < size_; ++i) {
      if (!fixed[i]) {
        vector<int> temp;
        for (int j = i; j < size_; ++j) {
          if (same(i, j))
            temp.push_back(j), fixed[j] = true;
        }
        res.push_back(temp);
      }
    }
    return res;
  }
} uf;

string str;
int a[MAX];
int b[MAX];
int N;
pint seg[MAX];

int sum[MAX];

bool solve() {
  int n = str.size() + 1;

  memset(sum, 0, sizeof(sum));
  for (int i = 0; i < n; ++i) {
    int r = uf.root(i);
    sum[r] += b[i];
  }
  for (int i = 0; i < MAX; ++i) {
    if (sum[i] % 26 != 0)
      return false;
  }

  return true;
}

int main() {
  while (cin >> str >> N) {
    int n = str.size() + 1;
    uf.init(n);
    for (int i = 0; i < N; ++i) {
      cin >> seg[i].first >> seg[i].second;
      --seg[i].first;
      uf.connect(seg[i].first, seg[i].second);
    }
    for (int i = 0; i < n / 2; ++i) {
      int j = n - i - 1;
      uf.connect(i, j);
    }

    memset(a, 0, sizeof(a));
    for (int i = 0; i < str.size(); ++i) {
      a[i] = (int)(str[i] - 'a');
    }
    b[0] = a[0];
    for (int i = 0; i < str.size(); ++i) {
      b[i + 1] = a[i + 1] - a[i];
      if (b[i + 1] < 0)
        b[i + 1] += 26;
      // cout << i + 1 << ", " << a[i+1] << ", " << b[i+1] << endl;
    }
    // COUT(uf);

    if (solve())
      puts("YES");
    else
      puts("NO");
  }
}


#include <bits/stdc++.h>
using namespace std;
typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x, to) for (x = 0; x < (to); x++)
#define FORR(x, arr) for (auto &x : arr)
#define ITR(x, c) for (__typeof(c.begin()) x = c.begin(); x != c.end(); x++)
#define ALL(a) (a.begin()), (a.end())
#define ZERO(a) memset(a, 0, sizeof(a))
#define MINUS(a) memset(a, 0xff, sizeof(a))
//-------------------------------------------------------

int L, N;
string S;
vector<int> R[101010];
ll sum[101010];

void solve() {
  int i, j, k, l, r, x, y;
  string s;

  cin >> S >> N;
  L = S.size();

  FORR(c, S) c -= 'a';
  FOR(i, N) {
    cin >> x >> y;
    x--, y--;
    if (y < (L + 1) / 2) {
      R[x].push_back(y);
    } else if (x >= L / 2) {
      R[L - 1 - y].push_back(L - 1 - x);
    } else {
      y = L - 1 - y;
      if (x < y)
        R[x].push_back(y - 1);
      if (y < x)
        R[y].push_back(x - 1);
    }
  }

  FOR(i, L / 2) {
    if (i)
      sum[i] += sum[i - 1];
    int dif = ((S[L - 1 - i] - (S[i] + sum[i])) % 26 + 26) % 26;
    sort(ALL(R[i]));
    FOR(j, R[i].size() - 1) {
      if (R[i][j] != R[i][j + 1])
        R[R[i][j] + 1].push_back(R[i][j + 1]);
    }
    if (dif == 0)
      continue;
    if (R[i].empty())
      return _P("NO\\n");
    sum[i] += dif;
    sum[R[i][0] + 1] -= dif;
  }
  _P("YES\\n");
}

int main(int argc, char **argv) {
  string s;
  int i;
  if (argc == 1)
    ios::sync_with_stdio(false), cin.tie(0);
  FOR(i, argc - 1) s += argv[i + 1], s += '\\n';
  FOR(i, s.size()) ungetc(s[s.size() - 1 - i], stdin);
  cout.tie(0);
  solve();
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x, to) for (x = 0; x < (to); x++)
#define FORR(x, arr) for (auto &x : arr)
#define ITR(x, c) for (__typeof(c.begin()) x = c.begin(); x != c.end(); x++)
#define ALL(a) (a.begin()), (a.end())
#define ZERO(a) memset(a, 0, sizeof(a))
#define MINUS(a) memset(a, 0xff, sizeof(a))
//-------------------------------------------------------

int L, N;
string S;
vector<int> R[101010];
ll sum[101010];

void solve() {
  int i, j, k, l, r, x, y;
  string s;

  cin >> S >> N;
  L = S.size();

  FORR(c, S) c -= 'a';
  FOR(i, N) {
    cin >> x >> y;
    x--, y--;
    if (y < (L + 1) / 2) {
      R[x].push_back(y);
    } else if (x >= L / 2) {
      R[L - 1 - y].push_back(L - 1 - x);
    } else {
      y = L - 1 - y;
      if (x < y)
        R[x].push_back(y - 1);
      if (y < x)
        R[y].push_back(x - 1);
    }
  }

  FOR(i, L / 2) {
    if (i)
      sum[i] += sum[i - 1];
    int dif = ((S[L - 1 - i] - (S[i] + sum[i])) % 26 + 26) % 26;
    sort(ALL(R[i]));
    if (R[i].size() > 1) {
      FOR(j, R[i].size() - 1) {
        if (R[i][j] != R[i][j + 1])
          R[R[i][j] + 1].push_back(R[i][j + 1]);
      }
    }
    if (dif == 0)
      continue;
    if (R[i].empty())
      return _P("NO\\n");
    sum[i] += dif;
    sum[R[i][0] + 1] -= dif;
  }
  _P("YES\\n");
}

int main(int argc, char **argv) {
  string s;
  int i;
  if (argc == 1)
    ios::sync_with_stdio(false), cin.tie(0);
  FOR(i, argc - 1) s += argv[i + 1], s += '\\n';
  FOR(i, s.size()) ungetc(s[s.size() - 1 - i], stdin);
  cout.tie(0);
  solve();
  return 0;
}


#include <bits/stdc++.h>
#define maxn 100100
using namespace std;
int n, sum[maxn * 2], tp, m, a[maxn], f[maxn];
char s[maxn];
int g(int x) { return x < 0 ? x + 26 : x; }
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
int main() {
  scanf("%s%d", s + 1, &n);
  int m = strlen(s + 1);
  for (int i = 1; i <= m; ++i)
    s[i] -= 'a', f[i] = i;
  f[m + 1] = m + 1;
  for (int i = m + 1; i >= 1; --i)
    s[i] = g(s[i] - s[i - 1]);
  for (int i = 1, l, r; i <= n; ++i)
    scanf("%d%d", &l, &r), f[find(l)] = find(r + 1);
  for (int i = 1; i <= m - i + 2; ++i)
    f[find(i)] = find(m + 2 - i);
  for (int i = 1; i <= m + 1; ++i)
    sum[find(i)] += s[i];
  for (int i = 1; i <= m + 1; ++i)
    if (i == find(i) && sum[i] % 26)
      return puts("NO");
  puts("YES");
}

#include <bits/stdc++.h>
#define maxn 1000100
using namespace std;
int n, sum[maxn * 2], tp, m, a[maxn], f[maxn];
char s[maxn];
int g(int x) { return x < 0 ? x + 26 : x; }
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
int main() {
  scanf("%s%d", s + 1, &n);
  int m = strlen(s + 1);
  for (int i = 1; i <= m; ++i)
    s[i] -= 'a', f[i] = i;
  f[m + 1] = m + 1;
  for (int i = m + 1; i >= 1; --i)
    s[i] = g(s[i] - s[i - 1]);
  for (int i = 1, l, r; i <= n; ++i)
    scanf("%d%d", &l, &r), f[find(l)] = find(r + 1);
  for (int i = 1; i <= m - i + 2; ++i)
    f[find(i)] = find(m + 2 - i);
  for (int i = 1; i <= m + 1; ++i)
    sum[find(i)] += s[i];
  for (int i = 1; i <= m + 1; ++i)
    if (i == find(i) && sum[i] % 26)
      return puts("NO"), 0;
  puts("YES");
}


#pragma comment(linker, "/STACK:512000000")
#define _CRT_SECURE_NO_WARNINGS
/*#if !defined(YCM) && 0
#define _FORTIFY_SOURCE 0
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("avx,tune=native")
#include <stdio.h>
#endif*/
// #include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

#define all(a) a.begin(), a.end()
typedef long long li;
typedef long double ld;
void solve(bool);
void precalc();
clock_t start;
int main() {
#ifdef AIM
  freopen("/home/alexandero/ClionProjects/ACM/input.txt", "r", stdin);
  // freopen("/home/alexandero/ClionProjects/ACM/output.txt", "w", stdout);
  // freopen("out.txt", "w", stdout);
#else
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
#endif
  start = clock();
  int t = 1;
  cout.sync_with_stdio(0);
  cin.tie(0);
  precalc();
  cout.precision(10);
  cout << fixed;
  // cin >> t;
  int testNum = 1;
  while (t--) {
    // cout << "Case #" << testNum++ << ": ";
    // cerr << testNum << endl;
    solve(true);
    // cerr << testNum - 1 << endl;
  }
  cout.flush();
#ifdef AIM1
  while (true) {
    solve(false);
  }
#endif

#ifdef AIM
  cerr << "\\n\\n time: " << (clock() - start) / 1.0 / CLOCKS_PER_SEC << "\\n\\n";
#endif

  return 0;
}

// BE CAREFUL: IS INT REALLY INT?

template <typename T> T binpow(T q, T w, T mod) {
  if (!w)
    return 1 % mod;
  if (w & 1)
    return q * 1LL * binpow(q, w - 1, mod) % mod;
  return binpow(q * 1LL * q % mod, w / 2, mod);
}

template <typename T> T gcd(T q, T w) {
  while (w) {
    q %= w;
    swap(q, w);
  }
  return q;
}
template <typename T> T lcm(T q, T w) { return q / gcd(q, w) * w; }

template <typename T> void make_unique(vector<T> &a) {
  sort(all(a));
  a.erase(unique(all(a)), a.end());
}

template <typename T> void relax_min(T &cur, T val) { cur = min(cur, val); }

template <typename T> void relax_max(T &cur, T val) { cur = max(cur, val); }

void precalc() {}

// #define int li
// const int mod = 1000000007;

void solve(bool read) {
  string s;
  cin >> s;
  int n;
  cin >> n;
  int is_odd = (int)s.length() % 2;
  int half = (int)s.length() / 2;
  int len = (int)s.length();
  vector<pair<int, int>> segs;
  for (int i = 0; i < n; ++i) {
    int l, r;
    cin >> l >> r;
    --l;
    --r;
    if (l >= half) {
      l = len - 1 - l;
      r = len - 1 - r;
      swap(l, r);
    }
    if (l == half) {
      continue;
    }
    if (r <= half) {
      segs.push_back({l, min(r, half - is_odd)});
      continue;
    }
    if (is_odd) {
      if (half - l < r - half) {
        l = len - 1 - l;
        r = len - 1 - r;
        swap(l, r);
      }
      segs.push_back({l, len - 1 - r - 1});
      continue;
    }
    if (half - 1 - l < r - half) {
      l = len - 1 - l;
      r = len - 1 - r;
      swap(l, r);
    }
    segs.push_back({l, len - 1 - r - 1});
  }

  vector<vector<int>> starts(half);
  vector<vector<int>> ends(half + 1);
  vector<int> diff(half);
  for (int i = 0; i < half; ++i) {
    diff[i] = (s[i] + 26 - s[len - 1 - i]) % 26;
  }
  for (int cur = 0; cur < segs.size(); ++cur) {
    auto item = segs[cur];
    if (item.second >= item.first) {
      starts[item.first].push_back(cur);
      ends[item.second + 1].push_back(cur);
    }
  }

  set<pair<int, int>> a;
  for (int i = 0; i < half; ++i) {
    /*if (starts[i].empty() && ends[i].empty() && i > 0 && diff[i] != diff[i -
    1]) { cout << "NO\\n"; return;
    }*/
    for (int id : starts[i]) {
      a.insert({i, id});
    }
    int min_deleted = i;
    for (int id : ends[i]) {
      min_deleted = min(min_deleted, segs[id].first);
      a.erase({segs[id].first, id});
    }
    if (a.empty() && diff[i] != 0) {
      cout << "NO\\n";
      return;
    }
    if (!a.empty() && min_deleted > a.rbegin()->first && min_deleted &&
        diff[min_deleted - 1] != diff[i]) {
      cout << "NO\\n";
      return;
    }
  }

  cout << "YES\\n";
}

#pragma comment(linker, "/STACK:512000000")
#define _CRT_SECURE_NO_WARNINGS
/*#if !defined(YCM) && 0
#define _FORTIFY_SOURCE 0
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("avx,tune=native")
#include <stdio.h>
#endif*/
// #include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

#define all(a) a.begin(), a.end()
typedef long long li;
typedef long double ld;
void solve(bool);
void precalc();
clock_t start;
int main() {
#ifdef AIM
  freopen("/home/alexandero/ClionProjects/ACM/input.txt", "r", stdin);
  // freopen("/home/alexandero/ClionProjects/ACM/output.txt", "w", stdout);
  // freopen("out.txt", "w", stdout);
#else
  // freopen("input.txt", "r", stdin);
  // freopen("output.txt", "w", stdout);
#endif
  start = clock();
  int t = 1;
  cout.sync_with_stdio(0);
  cin.tie(0);
  precalc();
  cout.precision(10);
  cout << fixed;
  // cin >> t;
  int testNum = 1;
  while (t--) {
    // cout << "Case #" << testNum++ << ": ";
    // cerr << testNum << endl;
    solve(true);
    // cerr << testNum - 1 << endl;
  }
  cout.flush();
#ifdef AIM1
  while (true) {
    solve(false);
  }
#endif

#ifdef AIM
  cerr << "\\n\\n time: " << (clock() - start) / 1.0 / CLOCKS_PER_SEC << "\\n\\n";
#endif

  return 0;
}

// BE CAREFUL: IS INT REALLY INT?

template <typename T> T binpow(T q, T w, T mod) {
  if (!w)
    return 1 % mod;
  if (w & 1)
    return q * 1LL * binpow(q, w - 1, mod) % mod;
  return binpow(q * 1LL * q % mod, w / 2, mod);
}

template <typename T> T gcd(T q, T w) {
  while (w) {
    q %= w;
    swap(q, w);
  }
  return q;
}
template <typename T> T lcm(T q, T w) { return q / gcd(q, w) * w; }

template <typename T> void make_unique(vector<T> &a) {
  sort(all(a));
  a.erase(unique(all(a)), a.end());
}

template <typename T> void relax_min(T &cur, T val) { cur = min(cur, val); }

template <typename T> void relax_max(T &cur, T val) { cur = max(cur, val); }

void precalc() {}

// #define int li
// const int mod = 1000000007;

void solve(bool read) {
  string s;
  if (read) {
    cin >> s;
  } else {
    s = string(1000, 'a');
  }
  int n;
  if (read) {
    cin >> n;
  } else {
    n = 1000;
  }
  int is_odd = (int)s.length() % 2;
  int half = (int)s.length() / 2;
  int len = (int)s.length();
  vector<pair<int, int>> segs;
  for (int i = 0; i < n; ++i) {
    int l, r;
    if (read) {
      cin >> l >> r;
    } else {
      do {
        l = rand() % n + 1;
        r = rand() % n + 1;
      } while (l > r);
    }
    --l;
    --r;
    if (l >= half) {
      l = len - 1 - l;
      r = len - 1 - r;
      swap(l, r);
    }
    if (l == half) {
      assert(is_odd);
      continue;
    }
    if (is_odd && r == half) {
      --r;
    }
    if (r < half) {
      segs.push_back({l, r});
      continue;
    }
    if (is_odd) {
      if (half - l < r - half) {
        l = len - 1 - l;
        r = len - 1 - r;
        swap(l, r);
      }
      segs.push_back({l, len - 1 - r - 1});
      continue;
    }
    if (half - 1 - l < r - half) {
      l = len - 1 - l;
      r = len - 1 - r;
      swap(l, r);
    }
    segs.push_back({l, len - 1 - r - 1});
  }

  vector<vector<int>> starts(half);
  vector<int> diff(half);
  for (int i = 0; i < half; ++i) {
    diff[i] = (s[i] + 26 - s[len - 1 - i]) % 26;
  }
  for (int cur = 0; cur < segs.size(); ++cur) {
    auto item = segs[cur];
    if (item.second >= item.first) {
      starts[item.first].push_back(item.second + 1);
    }
  }
  vector<int> add(half + 1, 0);

  for (int i = 0; i < half; ++i) {
    make_unique(starts[i]);
    for (int j = 1; j < starts[i].size(); ++j) {
      starts[starts[i][j - 1]].push_back(starts[i][j]);
    }
    if (i) {
      add[i] += add[i - 1];
    }
    int need = (diff[i] - add[i] + 26) % 26;
    if (need) {
      if (starts[i].empty()) {
        cout << "NO\\n";
        return;
      }
      add[i] += need;
      add[starts[i][0]] -= need;
    }
  }
  cout << "YES\\n";
}


#include <bits/stdc++.h>
#define REP(i, a, n) for (ll i = ((ll)a); i < ((ll)n); i++)
#define MOD 1000000007LL
using namespace std;
typedef long long ll;

ll N, K;

int main(void) {
  cin >> N >> K;

  ll p = 1;
  REP(i, 0, N - 1) p = (p * (K + 1)) % MOD;
  ll all = (p * ((K * (K + 1) / 2) % MOD)) % MOD * N % MOD;

  vector<vector<ll>> dp(N + 1, vector<ll>(3500, 0));
  dp[0][0] = 1;
  REP(i, 0, N) {
    REP(j, 0, K + 1) {
      REP(k, 0, 3500) {
        if (j <= N - i) {
          dp[i + 1][k + (k + j) / (N - i)] += dp[i][k];
          dp[i + 1][k + (k + j) / (N - i)] %= MOD;
        } else {
          dp[i + 1][k] += dp[i][k];
          dp[i + 1][k] %= MOD;
        }
      }
    }
  }

  ll ans = 0;
  REP(i, 0, 3500) {
    ans += (dp[N][i] * i) % MOD;
    ans %= MOD;
  }
  cout << (all - ans + MOD) % MOD << endl;
}

#include <bits/stdc++.h>
#define REP(i, a, n) for (ll i = ((ll)a); i < ((ll)n); i++)
#define MOD 1000000007LL
using namespace std;
typedef long long ll;

ll N, K;

int main(void) {
  cin >> N >> K;

  ll p = 1;
  REP(i, 0, N - 1) p = (p * (K + 1)) % MOD;
  ll all = (p * ((K * (K + 1) / 2) % MOD)) % MOD * N % MOD;

  vector<vector<ll>> dp(N + 1, vector<ll>(3500, 0));
  dp[0][0] = 1;
  REP(i, 0, N) {
    REP(j, 0, K + 1) {
      REP(k, 0, 3500) {
        if (dp[i][k] == 0)
          continue;
        if (j <= N - i) {
          if (k + (k + j) / (N - i) < 3500) {
            dp[i + 1][k + (k + j) / (N - i)] += dp[i][k];
            dp[i + 1][k + (k + j) / (N - i)] %= MOD;
          }
        } else {
          dp[i + 1][k] += dp[i][k];
          dp[i + 1][k] %= MOD;
        }
      }
    }
  }

  ll ans = 0;
  REP(i, 0, 3500) {
    ans += (dp[N][i] * i) % MOD;
    ans %= MOD;
  }
  cout << (all - ans + MOD) % MOD << endl;
}


#include <stdio.h>

int main() {
  const long long mod = 1000000007;
  int N, K;
  scanf("%d %d", &N, &K);
  long long pw[101] = {
      1,
  };
  for (int i = 1; i <= N; i++)
    pw[i] = pw[i - 1] * (K + 1) % mod;

  long long ans = N * K * (K + 1) / 2 * pw[N - 1] % mod;
  long long prv[1000] = {
      1,
  };
  for (int i = N; i >= 1; i--) {
    long long nxt[1000] = {
        0,
    };
    for (int k = 0; k <= K; k++) {
      for (int j = 0; j < 1000; j++)
        if (prv[j]) {
          int v = (j + k) / i;
          if (k > i)
            v = 0;
          ans = (ans + mod - pw[i - 1] * v % mod * prv[j] % mod) % mod;
          nxt[j + v] = (nxt[j + v] + prv[j]) % mod;
        }
    }
    for (int j = 0; j < 1000; j++)
      prv[j] = nxt[j];
  }

  printf("%lld\\n", ans);

  return 0;
}

#include <stdio.h>

int main() {
  const long long mod = 1000000007;
  int N, K;
  scanf("%d %d", &N, &K);
  long long pw[101] = {
      1,
  };
  for (int i = 1; i <= N; i++)
    pw[i] = pw[i - 1] * (K + 1) % mod;

  long long ans = N * K * (K + 1) / 2 * pw[N - 1] % mod;
  long long prv[8000] = {
      1,
  };
  for (int i = N; i >= 1; i--) {
    long long nxt[8000] = {
        0,
    };
    for (int k = 0; k <= K; k++) {
      for (int j = 0; j < 8000; j++)
        if (prv[j]) {
          int v = (j + k) / i;
          if (k > i)
            v = 0;
          ans = (ans + mod - pw[i - 1] * v % mod * prv[j] % mod) % mod;
          nxt[j + v] = (nxt[j + v] + prv[j]) % mod;
        }
    }
    for (int j = 0; j < 8000; j++)
      prv[j] = nxt[j];
  }

  printf("%lld\\n", ans);

  return 0;
}


#include "bits/stdc++.h"
using namespace std;
const int maxn = 101;
const int magic = 4040;
const int mod = 1000000007;
long long o[maxn][maxn * maxn];
int main() {
  int n, k;
  scanf("%d %d", &n, &k);
  o[n + 1][0] = 1;
  for (int e = n; e >= 1; e--) {
    for (int s = 0; s < magic; s++) {
      if (o[e + 1][s] == 0)
        continue;
      for (int f = 0; f <= k; f++) {
        if (f <= e) {
          o[e][s + (f + s) / e] += o[e + 1][s];
          o[e][s + (f + s) / e] %= mod;
        } else {
          o[e][s] += o[e + 1][s];
          o[e][s] %= mod;
        }
      }
    }
  }
  long long comb = k * (k + 1) / 2;
  comb *= n;
  comb %= mod;
  for (int e = 0; e < n - 1; e++)
    comb *= (k + 1), comb %= mod;
  long long ans = comb;
  for (int e = 0; e < magic; e++)
    ans += mod - (e * o[1][e] % mod), ans %= mod;
  cout << ans << endl;
  return 0;
}

#include "bits/stdc++.h"
using namespace std;
const int maxn = 103;
const int magic = 4040;
const int mod = 1000000007;
long long o[maxn][maxn * maxn];
int main() {
  int n, k;
  scanf("%d %d", &n, &k);
  o[n + 1][0] = 1;
  for (int e = n; e >= 1; e--) {
    for (int s = 0; s < magic; s++) {
      if (o[e + 1][s] == 0)
        continue;
      for (int f = 0; f <= k; f++) {
        if (f <= e) {
          o[e][s + (f + s) / e] += o[e + 1][s];
          o[e][s + (f + s) / e] %= mod;
        } else {
          o[e][s] += o[e + 1][s];
          o[e][s] %= mod;
        }
      }
    }
  }
  long long comb = k * (k + 1) / 2;
  comb *= n;
  comb %= mod;
  for (int e = 0; e < n - 1; e++)
    comb *= (k + 1), comb %= mod;
  long long ans = comb;
  for (int e = 0; e < magic; e++)
    ans += mod - (e * o[1][e] % mod), ans %= mod;
  cout << ans << endl;
  return 0;
}


#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <utility>
#include <vector>

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<VI> VVI;
#define MP make_pair
#define PB push_back
const ll mod = 1000000007;

ll dp[101][5000];
long long ruijo(long long x, ll n) {
  long long p, ans;
  if (n == 0)
    return 1;
  if (n == 1)
    return x;
  if (n % 2) {
    p = ruijo(x, n / 2);
    ans = (x * p) % mod;
    ans = (ans * p) % mod;
    return ans;
  } else {
    p = ruijo(x, n / 2);
    ans = (p * p) % mod;
    return ans;
  }
}
ll n, k;

ll element_count(ll x, ll y, ll z) {
  ll a = max((ll)0, y * z - x);
  ll b = min(y, y * (z + 1) - 1 - x);
  if (a > b)
    return (ll)0;
  else
    return b - a + 1;
}

int main() {
  cin >> n >> k;
  for (ll i = n; i > k; i--) {
    dp[i][0] = ruijo(k + 1, (n - i + 1));
  }
  dp[k][0] = k * ruijo(k + 1, n - k);
  dp[k][1] = 1 * ruijo(k + 1, n - k);
  for (ll i = k - 1; i >= 1; i--) {
    for (ll j = 0; j < 4000; j++) {
      if (j == 0) {
        dp[i][0] = k * dp[i + 1][0] % mod;
      } else {
        for (ll m = 0; m <= j; m++) {
          if (j != m) {
            dp[i][j] =
                (dp[i][j] + element_count(m, i, j - m) * dp[i + 1][m]) % mod;
          } else {
            dp[i][j] = (dp[i][j] + (k - i) * dp[i + 1][m]) % mod;
            if (i - m - 1 >= 0) {
              dp[i][j] = (dp[i][j] + (i - m) * dp[i + 1][m]) % mod;
            }
          }
        }
      }
    }
  }
  ll ans = 0;
  for (int i = 1; i < 4000; i++) {
    ans = (ans + i * dp[1][i]) % mod;
  }
  ll w = (n * ruijo(k + 1, n - 1)) % mod;
  ll s = ((k * (k + 1)) / 2) % mod;
  s = (s * w) % mod;
  cout << (s - ans + mod) % mod << endl;
  return 0;
}

#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <utility>
#include <vector>

using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<VI> VVI;
#define MP make_pair
#define PB push_back
const ll mod = 1000000007;

ll dp[101][4010];
long long ruijo(long long x, ll n) {
  long long p, ans;
  if (n == 0)
    return 1;
  if (n == 1)
    return x;
  if (n % 2) {
    p = ruijo(x, n / 2);
    ans = (x * p) % mod;
    ans = (ans * p) % mod;
    return ans;
  } else {
    p = ruijo(x, n / 2);
    ans = (p * p) % mod;
    return ans;
  }
}
ll n, k;

ll element_count(ll x, ll y, ll z) {
  ll a = max((ll)0, y * z - x);
  ll b = min(y, y * (z + 1) - 1 - x);
  if (a > b)
    return (ll)0;
  else
    return b - a + 1;
}

int main() {
  cin >> n >> k;
  for (ll i = n; i > k; i--) {
    dp[i][0] = ruijo(k + 1, (n - i + 1));
  }
  dp[k][0] = k * ruijo(k + 1, n - k);
  dp[k][1] = 1 * ruijo(k + 1, n - k);
  for (ll i = k - 1; i >= 1; i--) {
    ll p;
    if (i == 1) {
      p = 4000;
    }
    if (i == 2) {
      p = 3000;
    }
    if (i == 3) {
      p = 2000;
    }
    if (i >= 4) {
      p = 1000;
    }
    for (ll j = 0; j < p; j++) {
      if (j == 0) {
        dp[i][0] = k * dp[i + 1][0] % mod;
      } else {
        for (ll m = 0; m <= j; m++) {
          if (j != m) {
            dp[i][j] =
                (dp[i][j] + element_count(m, i, j - m) * dp[i + 1][m]) % mod;
          } else {
            dp[i][j] = (dp[i][j] + (k - i) * dp[i + 1][m]) % mod;
            if (i - m - 1 >= 0) {
              dp[i][j] = (dp[i][j] + (i - m) * dp[i + 1][m]) % mod;
            }
          }
        }
      }
    }
  }
  ll ans = 0;
  for (int i = 1; i < 4000; i++) {
    ans = (ans + i * dp[1][i]) % mod;
  }
  ll w = (n * ruijo(k + 1, n - 1)) % mod;
  ll s = ((k * (k + 1)) / 2) % mod;
  s = (s * w) % mod;
  cout << (s - ans + mod) % mod << endl;
  return 0;
}


#include <bits/stdc++.h>
#define ADD(a, b) a = (a + ll(b)) % mod
#define MUL(a, b) a = (a * ll(b)) % mod
#define MAX(a, b) a = max(a, b)
#define MIN(a, b) a = min(a, b)
#define rep(i, a, b) for (int i = int(a); i < int(b); i++)
#define rer(i, a, b) for (int i = int(a) - 1; i >= int(b); i--)
#define all(a) (a).begin(), (a).end()
#define sz(v) (int)(v).size()
#define pb push_back
#define sec second
#define fst first
#define debug(fmt, ...) Debug(__LINE__, ":", fmt, ##__VA_ARGS__)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef pair<int, pi> ppi;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vl> mat;
typedef complex<double> comp;
void Debug() { cout << '\\n'; }
template <class FIRST, class... REST> void Debug(FIRST arg, REST... rest) {
  cout << arg << " ";
  Debug(rest...);
}
template <class T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << "[";
  if (!v.empty()) {
    rep(i, 0, sz(v) - 1) out << v[i] << ", ";
    out << v.back();
  }
  out << "]";
  return out;
}
template <class S, class T>
ostream &operator<<(ostream &out, const pair<S, T> &v) {
  out << "(" << v.first << ", " << v.second << ")";
  return out;
}
const int MAX_N = 200010;
const int MAX_V = 100010;
const double eps = 1e-6;
const ll mod = 1000000007;
const int inf = 1 << 29;
const ll linf = 1LL << 60;
const double PI = 3.14159265358979323846;
///////////////////////////////////////////////////////////////////////////////////////////////////

int N, M;
int X, Y;
int A[50][50];
int S[50][50];
int dp[50][50][50][50];

int get_sum(int x1, int y1, int x2, int y2) {
  return S[x2 + 1][y2 + 1] - S[x2 + 1][y1] - S[x1][y2 + 1] + S[x1][y1];
}

void solve() {
  cin >> N >> M;
  rep(i, 0, N) {
    rep(j, 0, M) {
      char c;
      cin >> c;
      if (c == '+')
        A[i][j] = 0;
      else if (c == '#')
        A[i][j] = 1;
      else {
        A[i][j] = 0;
        X = i;
        Y = j;
      }
    }
  }
  rep(i, 0, N) {
    rep(j, 0, M) {
      S[i + 1][j + 1] = A[i][j] + S[i + 1][j] + S[i][j + 1] - S[i][j];
    }
  }
  rep(x1, 0, N) {
    rep(y1, 0, M) {
      rep(x2, x1, N) {
        rep(y2, y1, M) { dp[x1][y1][x2][y2] = N * M; }
      }
    }
  }
  dp[0][0][N - 1][M - 1] = 0;
  rep(x1, 0, N) {
    rep(y1, 0, M) {
      rer(x2, N, x1) {
        rer(y2, M, y1) {
          int left = get_sum(x1, y1, x1, y2);
          int up = get_sum(x1, y1, x2, y1);
          int right = get_sum(x2, y1, x2, y2);
          int down = get_sum(x1, y2, x2, y2);
          MIN(dp[x1 + 1][y1][x2][y2], left + dp[x1][y1][x2][y2]);
          MIN(dp[x1][y1 + 1][x2][y2], up + dp[x1][y1][x2][y2]);
          MIN(dp[x1][y1][x2 - 1][y2], right + dp[x1][y1][x2][y2]);
          MIN(dp[x1][y1][x2][y2 - 1], down + dp[x1][y1][x2][y2]);
          if (A[x1][y1])
            MIN(dp[x1 + 1][y1 + 1][x2][y2], left + up - 2 + dp[x1][y1][x2][y2]);
          if (A[x1][y2])
            MIN(dp[x1 + 1][y1][x2][y2 - 1],
                left + down - 2 + dp[x1][y1][x2][y2]);
          if (A[x2][y1])
            MIN(dp[x1][y1 + 1][x2 - 1][y2],
                right + up - 2 + dp[x1][y1][x2][y2]);
          if (A[x2][y2])
            MIN(dp[x1][y1][x2 - 1][y2 - 1],
                right + down - 2 + dp[x1][y1][x2][y2]);
        }
      }
    }
  }
  int ans = N * M;
  rep(x1, 0, N) {
    rep(y1, 0, M) {
      rep(x2, x1, N) {
        rep(y2, y1, M) {
          if (!(x1 <= X && X <= x2 && y1 <= Y && Y <= y2))
            continue;
          MIN(ans, dp[x1][y1][x2][y2] + get_sum(x1, y1, X, Y));
          MIN(ans, dp[x1][y1][x2][y2] + get_sum(X, y1, x2, Y));
          MIN(ans, dp[x1][y1][x2][y2] + get_sum(x1, Y, X, y2));
          MIN(ans, dp[x1][y1][x2][y2] + get_sum(X, Y, x2, y2));
        }
      }
    }
  }
  cout << ans << "\\n";
}

int main() {
#ifndef LOCAL
  ios::sync_with_stdio(false);
  cin.tie(0);
#endif
  cout << fixed;
  cout.precision(20);
  srand((unsigned int)time(NULL));
#ifdef LOCAL
  // freopen("in.txt", "wt", stdout); //for tester
  freopen("in.txt", "rt", stdin);
#endif
  solve();
#ifdef LOCAL
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\\n";
#endif
  return 0;
}

#include <bits/stdc++.h>
#define ADD(a, b) a = (a + ll(b)) % mod
#define MUL(a, b) a = (a * ll(b)) % mod
#define MAX(a, b) a = max(a, b)
#define MIN(a, b) a = min(a, b)
#define rep(i, a, b) for (int i = int(a); i < int(b); i++)
#define rer(i, a, b) for (int i = int(a) - 1; i >= int(b); i--)
#define all(a) (a).begin(), (a).end()
#define sz(v) (int)(v).size()
#define pb push_back
#define sec second
#define fst first
#define debug(fmt, ...) Debug(__LINE__, ":", fmt, ##__VA_ARGS__)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef pair<int, pi> ppi;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vl> mat;
typedef complex<double> comp;
void Debug() { cout << '\\n'; }
template <class FIRST, class... REST> void Debug(FIRST arg, REST... rest) {
  cout << arg << " ";
  Debug(rest...);
}
template <class T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << "[";
  if (!v.empty()) {
    rep(i, 0, sz(v) - 1) out << v[i] << ", ";
    out << v.back();
  }
  out << "]";
  return out;
}
template <class S, class T>
ostream &operator<<(ostream &out, const pair<S, T> &v) {
  out << "(" << v.first << ", " << v.second << ")";
  return out;
}
const int MAX_N = 200010;
const int MAX_V = 100010;
const double eps = 1e-6;
const ll mod = 1000000007;
const int inf = 1 << 29;
const ll linf = 1LL << 60;
const double PI = 3.14159265358979323846;
///////////////////////////////////////////////////////////////////////////////////////////////////

int N, M;
int X, Y;
int A[50][50];
int S[50][50];
int dp[50][50][50][50];

int get_sum(int x1, int y1, int x2, int y2) {
  return S[x2 + 1][y2 + 1] - S[x2 + 1][y1] - S[x1][y2 + 1] + S[x1][y1];
}

void solve() {
  cin >> N >> M;
  rep(i, 0, N) {
    rep(j, 0, M) {
      char c;
      cin >> c;
      if (c == '+')
        A[i][j] = 0;
      else if (c == '#')
        A[i][j] = 1;
      else {
        A[i][j] = 0;
        X = i;
        Y = j;
      }
    }
  }
  rep(i, 0, N) {
    rep(j, 0, M) {
      S[i + 1][j + 1] = A[i][j] + S[i + 1][j] + S[i][j + 1] - S[i][j];
    }
  }
  rep(x1, 0, N) {
    rep(y1, 0, M) {
      rep(x2, x1, N) {
        rep(y2, y1, M) { dp[x1][y1][x2][y2] = N * M; }
      }
    }
  }
  dp[0][0][N - 1][M - 1] = 0;
  rep(x1, 0, N) {
    rep(y1, 0, M) {
      rer(x2, N, x1) {
        rer(y2, M, y1) {
          rep(x, 0, x1 + 1) {
            rep(y, 0, y1 + 1) {
              MIN(dp[x1][y1][x2][y2], dp[x][y][x2][y2] +
                                          get_sum(x, y1, x1 - 1, y2) +
                                          get_sum(x1, y, x2, y1 - 1));
            }
          }

          rep(x, x2, N) {
            rep(y, 0, y1 + 1) {
              MIN(dp[x1][y1][x2][y2], dp[x1][y][x][y2] +
                                          get_sum(x1, y, x2, y1 - 1) +
                                          get_sum(x2 + 1, y1, x, y2));
            }
          }

          rep(x, 0, x1 + 1) {
            rep(y, y2, M) {
              MIN(dp[x1][y1][x2][y2], dp[x][y1][x2][y] +
                                          get_sum(x, y1, x1 - 1, y2) +
                                          get_sum(x1, y2 + 1, x2, y));
            }
          }

          rep(x, x2, N) {
            rep(y, y2, M) {
              MIN(dp[x1][y1][x2][y2], dp[x1][y1][x][y] +
                                          get_sum(x2 + 1, y1, x, y2) +
                                          get_sum(x1, y2 + 1, x2, y));
            }
          }
        }
      }
    }
  }
  int ans = N * M;
  rep(x1, 0, N) {
    rep(y1, 0, M) {
      rep(x2, x1, N) {
        rep(y2, y1, M) {
          if (!(x1 <= X && X <= x2 && y1 <= Y && Y <= y2))
            continue;
          MIN(ans, dp[x1][y1][x2][y2] + get_sum(x1, y1, X, Y));
          MIN(ans, dp[x1][y1][x2][y2] + get_sum(X, y1, x2, Y));
          MIN(ans, dp[x1][y1][x2][y2] + get_sum(x1, Y, X, y2));
          MIN(ans, dp[x1][y1][x2][y2] + get_sum(X, Y, x2, y2));
        }
      }
    }
  }
  cout << ans << "\\n";
}

int main() {
#ifndef LOCAL
  ios::sync_with_stdio(false);
  cin.tie(0);
#endif
  cout << fixed;
  cout.precision(20);
  srand((unsigned int)time(NULL));
#ifdef LOCAL
  // freopen("in.txt", "wt", stdout); //for tester
  freopen("in.txt", "rt", stdin);
#endif
  solve();
#ifdef LOCAL
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\\n";
#endif
  return 0;
}


#include <algorithm>
#include <queue>
#include <stdio.h>
#include <vector>
using namespace std;
typedef pair<int, int> pii;
typedef pair<pii, int> pi3;
int mini[1 << 18], maxi[1 << 18];
vector<pii> qs[1000000];
int ans[1000000];
int main() {
  int num;
  scanf("%d", &num);
  fill(maxi, maxi + (1 << num), 1000000000);
  for (int i = 0; i < (1 << num); i++) {
    int z;
    scanf("%d", &z);
    if (z > 0)
      mini[i] = maxi[i] = z;
  }
  for (int i = 0; i < num; i++) {
    for (int j = 0; j < (1 << num); j++) {
      if (j & (1 << i))
        maxi[j - (1 << i)] = min(maxi[j - (1 << i)], maxi[j]);
      else
        mini[j + (1 << i)] = max(mini[j + (1 << i)], mini[j]);
    }
  }
  // for (int i = 0; i < (1 << num); i++)printf("%d %d\\n", mini[i], maxi[i]);
  for (int i = 0; i < (1 << num); i++)
    qs[maxi[i]].push_back(make_pair(mini[i], i));
  priority_queue<pi3> que;
  for (int i = (1 << num); i >= 1; i--) {
    for (int j = 0; j < qs[i].size(); j++) {
      que.push(make_pair(make_pair(qs[i][j].first, i), qs[i][j].second));
    }
    if (que.empty()) {
      printf("NO\\n");
      return 0;
    }
    pi3 z = que.top();
    que.pop();
    if (!(z.first.first <= i && i <= z.first.second)) {
      printf("NO\\n");
      return 0;
    }
    ans[z.second] = i;
  }
  printf("YES\\n");
  for (int i = 0; i < (1 << num); i++) {
    int p = 0;
    for (int j = 0; j < num; j++)
      if (i & (1 << j))
        p += 1 << (num - 1 - j);
    printf("%d ", ans[p]);
  }
  printf("\\n");
}

#include <algorithm>
#include <queue>
#include <stdio.h>
#include <vector>
using namespace std;
typedef pair<int, int> pii;
typedef pair<pii, int> pi3;
int mini[1 << 18], maxi[1 << 18];
vector<pii> qs[1000000];
int ans[1000000];
int main() {
  int num;
  scanf("%d", &num);
  fill(maxi, maxi + (1 << num), 1 << num);
  fill(mini, mini + (1 << num), 1);
  for (int i = 0; i < (1 << num); i++) {
    int z;
    scanf("%d", &z);
    if (z > 0)
      mini[i] = maxi[i] = z;
  }
  for (int i = 0; i < num; i++) {
    for (int j = 0; j < (1 << num); j++) {
      if (j & (1 << i))
        maxi[j - (1 << i)] = min(maxi[j - (1 << i)], maxi[j]);
      else
        mini[j + (1 << i)] = max(mini[j + (1 << i)], mini[j]);
    }
  }
  // for (int i = 0; i < (1 << num); i++)printf("%d %d\\n", mini[i], maxi[i]);
  for (int i = 0; i < (1 << num); i++)
    qs[maxi[i]].push_back(make_pair(mini[i], i));
  priority_queue<pi3> que;
  for (int i = (1 << num); i >= 1; i--) {
    for (int j = 0; j < qs[i].size(); j++) {
      que.push(make_pair(make_pair(qs[i][j].first, i), qs[i][j].second));
    }
    if (que.empty()) {
      printf("NO\\n");
      return 0;
    }
    pi3 z = que.top();
    que.pop();
    if (!(z.first.first <= i && i <= z.first.second)) {
      printf("NO\\n");
      return 0;
    }
    ans[z.second] = i;
  }
  printf("YES\\n");
  for (int i = 0; i < (1 << num); i++) {
    int p = 0;
    for (int j = 0; j < num; j++)
      if (i & (1 << j))
        p += 1 << (num - 1 - j);
    printf("%d ", ans[p]);
  }
  printf("\\n");
}


#include <algorithm>
#include <stdio.h>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
typedef pair<ll, pii> pi3;
typedef vector<pair<vector<int>, vector<pi3>>> inher;
vector<pi3> ans;
ll dat[200000];
#define INF 1000000000000000000LL
class tree {
public:
  // ここからいじらないところ(辺重みがあるときはうまくいじる)
  vector<int>
      idx; // 元々の index 木が小さくなるたびに実際の index は付け替えられる
  vector<vector<pii>> pat;
  vector<bool> flag;
  int num, cent; // num は頂点数、cent は重心の頂点番号 (0 <= cent < num)
  int dfs1(int node) {
    if (flag[node])
      return 0;
    flag[node] = true;
    int s = 1, maxi = 0;
    for (int i = 0; i < pat[node].size(); i++) {
      int r = dfs1(pat[node][i].first);
      s += r, maxi = max(maxi, r);
    }
    if (maxi <= num / 2 && (num - s) <= num / 2)
      cent = node;
    return s;
  }
  void init(vector<int> zid, vector<pi3> ed) {
    idx = zid;
    num = idx.size();
    flag.resize(num);
    pat.resize(num);
    for (int i = 0; i < ed.size(); i++) {
      pat[ed[i].second.first].push_back(
          make_pair(ed[i].second.second, ed[i].first));
      pat[ed[i].second.second].push_back(
          make_pair(ed[i].second.first, ed[i].first));
    }
    dfs1(0);
    fill(flag.begin(), flag.end(), false);
  }
  vector<int> sub1;
  vector<pi3> sub2;
  void dfs2(int node) {
    if (flag[node])
      return;
    flag[node] = true;
    int t = sub1.size();
    sub1.push_back(idx[node]);
    for (int i = 0; i < pat[node].size(); i++) {
      if (!flag[pat[node][i].first]) {
        sub2.push_back(
            make_pair(pat[node][i].second, make_pair(t, sub1.size())));
        dfs2(pat[node][i].first);
      }
    }
  }
  inher decompose() {
    inher r;
    fill(flag.begin(), flag.end(), false);
    flag[cent] = true;
    for (int i = 0; i < pat[cent].size(); i++) {
      sub1.clear();
      sub2.clear();
      dfs2(pat[cent][i].first);
      r.push_back(make_pair(sub1, sub2));
    }
    return r;
  }
  ll mn;
  int rr;
  void dfs3(int node, ll dep) {
    if (flag[node])
      return;
    flag[node] = true;
    if (mn > dep + dat[idx[node]])
      mn = dep + dat[idx[node]], rr = idx[node];
    ans.push_back(make_pair(dat[idx[cent]] + dat[idx[node]] + dep,
                            make_pair(idx[cent], idx[node])));
    for (int i = 0; i < pat[node].size(); i++)
      dfs3(pat[node][i].first, dep + pat[node][i].second);
  }
  void dfs4(int node, ll dep, int r) {
    if (flag[node])
      return;
    flag[node] = true;
    ans.push_back(make_pair(dat[idx[node]] + dep, make_pair(r, idx[node])));
    // printf("%d %d\\n",r, idx[node]);
    for (int i = 0; i < pat[node].size(); i++)
      dfs4(pat[node][i].first, dep + pat[node][i].second, r);
  }
  // ここまでいじらないところ
  void solve() // いじるところ
  {
    flag[cent] = true;
    ll m1 = INF, m2 = INF;
    int r1 = -1, r2 = -1;
    int t = -1;
    for (int i = 0; i < pat[cent].size(); i++) {
      mn = INF, rr = -1;
      dfs3(pat[cent][i].first, pat[cent][i].second);
      if (m1 > mn)
        m2 = m1, r2 = r1, m1 = mn, r1 = rr, t = i;
      else if (m2 > mn)
        m2 = mn, r2 = rr;
    }
    fill(flag.begin(), flag.end(), false);
    flag[cent] = true;
    // printf("   %lld %d\\n", m1, r1);
    for (int i = 0; i < pat[cent].size(); i++) {
      ll z;
      int r;
      if (t != i)
        z = m1, r = r1;
      else
        z = m2, r = r2;
      dfs4(pat[cent][i].first, z + pat[cent][i].second, r);
    }
  }
};
/*
重心分解
idx = {0,1,...,N-1}, ed は辺全部 として呼ぶ
tr.init で木が作られて重心が求まる
tr.solve で本質をやる
tr.decompose で分解を計算
子に対する solve の結果を利用するときは cetroiddecomposition の返り値として渡す

再帰するごとに頂点番号を 0 から頂点数 - 1 に取り換えるので、その取り換えた後の
index -> もとの index を表すのが idx ed は取り換え後の index で頂点を表現する
*/
void centroiddecomposition(vector<int> idx, vector<pi3> ed) {
  // for (int i = 0; i < idx.size(); i++)printf("%d ", idx[i] + 1);
  // printf("\\n");
  if (idx.size() <= 2) {
    if (idx.size() == 2)
      ans.push_back(make_pair(ed[0].first + dat[idx[0]] + dat[idx[1]],
                              make_pair(idx[0], idx[1])));
    return;
  }
  tree tr;
  tr.init(idx, ed);
  tr.solve();
  inher r = tr.decompose();
  tr.idx.clear();
  tr.pat.clear();
  tr.flag.clear();
  tr.sub1.clear();
  tr.sub2.clear();
  for (int i = 0; i < r.size(); i++)
    centroiddecomposition(r[i].first, r[i].second);
}
#define SIZE 200000
class unionfind {
public:
  int par[SIZE];
  int ran[SIZE];
  int ren[SIZE];
  void init() {
    for (int i = 0; i < SIZE; i++) {
      par[i] = i;
      ran[i] = 0;
      ren[i] = 1;
    }
  }
  int find(int a) {
    if (a == par[a])
      return a;
    else
      return par[a] = find(par[a]);
  }
  void unite(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b)
      return;
    if (ran[a] > ran[b]) {
      par[b] = a;
      ren[a] += ren[b];
    } else {
      par[a] = b;
      ren[b] += ren[a];
    }
    if (ran[a] == ran[b])
      ran[b]++;
  }
};
unionfind uf;
int main() {
  int num;
  scanf("%d", &num);
  vector<int> zzd;
  vector<pi3> ed;
  for (int i = 0; i < num; i++)
    scanf("%lld", &dat[i]), zzd.push_back(i);
  for (int i = 0; i < num - 1; i++) {
    int za, zb, zc;
    scanf("%d%d%d", &za, &zb, &zc);
    za--, zb--;
    ed.push_back(make_pair(zc, make_pair(za, zb)));
  }
  centroiddecomposition(zzd, ed);
  sort(ans.begin(), ans.end());
  uf.init();
  ll ret = 0;
  for (int i = 0; i < ans.size(); i++) {
    // printf("%lld %lld  %lld\\n", ans[i].second.first + 1, ans[i].second.second
    // + 1, ans[i].first);
    if (uf.find(ans[i].second.first) != uf.find(ans[i].second.second)) {
      ret += ans[i].first;
      uf.unite(ans[i].second.first, ans[i].second.second);
    }
  }
  printf("%lld\\n", ret);
}

#include <algorithm>
#include <stdio.h>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, pii> pi3;
typedef vector<pair<vector<int>, vector<pi3>>> inher;
vector<pi3> ans;
ll dat[200000];
#define INF 1000000000000000000LL
class tree {
public:
  // ここからいじらないところ(辺重みがあるときはうまくいじる)
  vector<int>
      idx; // 元々の index 木が小さくなるたびに実際の index は付け替えられる
  vector<vector<pii>> pat;
  vector<bool> flag;
  int num, cent; // num は頂点数、cent は重心の頂点番号 (0 <= cent < num)
  int dfs1(int node) {
    if (flag[node])
      return 0;
    flag[node] = true;
    int s = 1, maxi = 0;
    for (int i = 0; i < pat[node].size(); i++) {
      int r = dfs1(pat[node][i].first);
      s += r, maxi = max(maxi, r);
    }
    if (maxi <= num / 2 && (num - s) <= num / 2)
      cent = node;
    return s;
  }
  void init(vector<int> zid, vector<pi3> ed) {
    idx = zid;
    num = idx.size();
    flag.resize(num);
    pat.resize(num);
    for (int i = 0; i < ed.size(); i++) {
      pat[ed[i].second.first].push_back(
          make_pair(ed[i].second.second, ed[i].first));
      pat[ed[i].second.second].push_back(
          make_pair(ed[i].second.first, ed[i].first));
    }
    dfs1(0);
    fill(flag.begin(), flag.end(), false);
  }
  vector<int> sub1;
  vector<pi3> sub2;
  void dfs2(int node) {
    if (flag[node])
      return;
    flag[node] = true;
    int t = sub1.size();
    sub1.push_back(idx[node]);
    for (int i = 0; i < pat[node].size(); i++) {
      if (!flag[pat[node][i].first]) {
        sub2.push_back(
            make_pair(pat[node][i].second, make_pair(t, sub1.size())));
        dfs2(pat[node][i].first);
      }
    }
  }
  inher decompose() {
    inher r;
    fill(flag.begin(), flag.end(), false);
    flag[cent] = true;
    for (int i = 0; i < pat[cent].size(); i++) {
      sub1.clear();
      sub2.clear();
      dfs2(pat[cent][i].first);
      r.push_back(make_pair(sub1, sub2));
    }
    return r;
  }
  ll mn;
  int rr;
  void dfs3(int node, ll dep) {
    if (flag[node])
      return;
    flag[node] = true;
    if (mn > dep + dat[idx[node]])
      mn = dep + dat[idx[node]], rr = idx[node];
    ans.push_back(make_pair(dat[idx[cent]] + dat[idx[node]] + dep,
                            make_pair(idx[cent], idx[node])));
    for (int i = 0; i < pat[node].size(); i++)
      dfs3(pat[node][i].first, dep + pat[node][i].second);
  }
  void dfs4(int node, ll dep, int r) {
    if (flag[node])
      return;
    flag[node] = true;
    ans.push_back(make_pair(dat[idx[node]] + dep, make_pair(r, idx[node])));
    // printf("%d %d\\n",r, idx[node]);
    for (int i = 0; i < pat[node].size(); i++)
      dfs4(pat[node][i].first, dep + pat[node][i].second, r);
  }
  // ここまでいじらないところ
  void solve() // いじるところ
  {
    flag[cent] = true;
    ll m1 = INF, m2 = INF;
    int r1 = -1, r2 = -1;
    int t = -1;
    for (int i = 0; i < pat[cent].size(); i++) {
      mn = INF, rr = -1;
      dfs3(pat[cent][i].first, pat[cent][i].second);
      if (m1 > mn)
        m2 = m1, r2 = r1, m1 = mn, r1 = rr, t = i;
      else if (m2 > mn)
        m2 = mn, r2 = rr;
    }
    fill(flag.begin(), flag.end(), false);
    flag[cent] = true;
    // printf("   %lld %d\\n", m1, r1);
    for (int i = 0; i < pat[cent].size(); i++) {
      ll z;
      int r;
      if (t != i)
        z = m1, r = r1;
      else
        z = m2, r = r2;
      dfs4(pat[cent][i].first, z + pat[cent][i].second, r);
    }
  }
};
/*
重心分解
idx = {0,1,...,N-1}, ed は辺全部 として呼ぶ
tr.init で木が作られて重心が求まる
tr.solve で本質をやる
tr.decompose で分解を計算
子に対する solve の結果を利用するときは cetroiddecomposition の返り値として渡す

再帰するごとに頂点番号を 0 から頂点数 - 1 に取り換えるので、その取り換えた後の
index -> もとの index を表すのが idx ed は取り換え後の index で頂点を表現する
*/
void centroiddecomposition(vector<int> idx, vector<pi3> ed) {
  // for (int i = 0; i < idx.size(); i++)printf("%d ", idx[i] + 1);
  // printf("\\n");
  if (idx.size() <= 2) {
    if (idx.size() == 2)
      ans.push_back(make_pair(ed[0].first + dat[idx[0]] + dat[idx[1]],
                              make_pair(idx[0], idx[1])));
    return;
  }
  tree tr;
  tr.init(idx, ed);
  tr.solve();
  inher r = tr.decompose();
  tr.idx.clear();
  tr.pat.clear();
  tr.flag.clear();
  tr.sub1.clear();
  tr.sub2.clear();
  for (int i = 0; i < r.size(); i++)
    centroiddecomposition(r[i].first, r[i].second);
}
#define SIZE 200000
class unionfind {
public:
  int par[SIZE];
  int ran[SIZE];
  int ren[SIZE];
  void init() {
    for (int i = 0; i < SIZE; i++) {
      par[i] = i;
      ran[i] = 0;
      ren[i] = 1;
    }
  }
  int find(int a) {
    if (a == par[a])
      return a;
    else
      return par[a] = find(par[a]);
  }
  void unite(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b)
      return;
    if (ran[a] > ran[b]) {
      par[b] = a;
      ren[a] += ren[b];
    } else {
      par[a] = b;
      ren[b] += ren[a];
    }
    if (ran[a] == ran[b])
      ran[b]++;
  }
};
unionfind uf;
int main() {
  int num;
  scanf("%d", &num);
  vector<int> zzd;
  vector<pi3> ed;
  for (int i = 0; i < num; i++)
    scanf("%lld", &dat[i]), zzd.push_back(i);
  for (int i = 0; i < num - 1; i++) {
    int za, zb, zc;
    scanf("%d%d%d", &za, &zb, &zc);
    za--, zb--;
    ed.push_back(make_pair(zc, make_pair(za, zb)));
  }
  centroiddecomposition(zzd, ed);
  sort(ans.begin(), ans.end());
  uf.init();
  ll ret = 0;
  for (int i = 0; i < ans.size(); i++) {
    // printf("%lld %lld  %lld\\n", ans[i].second.first + 1, ans[i].second.second
    // + 1, ans[i].first);
    if (uf.find(ans[i].second.first) != uf.find(ans[i].second.second)) {
      ret += ans[i].first;
      uf.unite(ans[i].second.first, ans[i].second.second);
    }
  }
  printf("%lld\\n", ret);
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

#pragma GCC optimize("O3")

using namespace std;
#define PB push_back
#define MP make_pair
#define LL long long
// #define int LL
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define RE(i, n) FOR(i, 1, n)
#define REP(i, n) FOR(i, 0, (int)(n)-1)
#define R(i, n) REP(i, n)
#define VI vector<int>
#define PII pair<int, int>
#define LD long double
#define FI first
#define SE second
#define st FI
#define nd SE
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())

#define unordered_map __fast_unordered_map
template <class Key, class Value, class Hash = std::hash<Key>>
using unordered_map = __gnu_pbds::gp_hash_table<Key, Value, Hash>;

template <class C> void mini(C &a4, C b4) { a4 = min(a4, b4); }
template <class C> void maxi(C &a4, C b4) { a4 = max(a4, b4); }

template <class TH> void _dbg(const char *sdbg, TH h) {
  cerr << sdbg << '=' << h << endl;
}
template <class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
  while (*sdbg != ',')
    cerr << *sdbg++;
  cerr << '=' << h << ',';
  _dbg(sdbg + 1, a...);
}

template <class T> ostream &operator<<(ostream &os, vector<T> V) {
  os << "[";
  for (auto vv : V)
    os << vv << ",";
  return os << "]";
}
template <class L, class R> ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.st << "," << P.nd << ")";
}
template <class L, class R, class X>
ostream &operator<<(ostream &os, tuple<L, R, X> P) {
  return os << "(" << get<0>(P) << "," << get<1>(P) << "," << get<2>(P) << ")";
}

#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (__VA_ARGS__)
#define cerr                                                                   \\
  if (0)                                                                       \\
  cout
#endif

const int MaxN = 2e5 + 100;

int groups[MaxN];
int centroid_subtree[MaxN];

struct BestInfo {
  LL dist;
  // int subtree_idx;
  int vert;

  bool operator<(const BestInfo &other) const { return dist < other.dist; }

  bool SameType(const BestInfo &other) const {
    return groups[vert] == groups[other.vert];
  }

  friend ostream &operator<<(ostream &os, const BestInfo &bi) {
    return os << "(" << bi.dist << "," << bi.vert << ")";
  }
};

vector<PII> adj[MaxN];
int weights[MaxN];
int N;
bool is_avail[MaxN];
int tree_size[MaxN];
int layer_idx[MaxN];
vector<int> conn_verts;
vector<BestInfo> best_dists[MaxN];

void DfsSizes(int v, int p) {
  tree_size[v] = 1;
  conn_verts.push_back(v);
  for (auto &E : adj[v]) {
    const int s = E.st;
    if (s == p) {
      continue;
    }
    if (!is_avail[s]) {
      continue;
    }
    DfsSizes(s, v);
    tree_size[v] += tree_size[s];
  }
}

void Centroids(int v, int layer) {
  conn_verts.clear();
  DfsSizes(v, v);

  int centroid = v;
  for (int s : conn_verts)
    if (2 * tree_size[s] >= tree_size[v] && tree_size[s] < tree_size[centroid])
      centroid = s;

  is_avail[centroid] = false;
  layer_idx[centroid] = layer;
  debug(centroid, layer);

  for (auto &E : adj[centroid])
    if (is_avail[E.st])
      Centroids(E.st, layer + 1);
}

const int kMaxBests = 4;
int subtree_idx;
int centr_cur;
LL dists_from_centroid[MaxN];
int vert_ptr[MaxN];
LL vert_ptr_dist[MaxN];

void DfsDists(int v, int p, LL cur_dist, vector<BestInfo> &bests) {
  debug(v, p, centr_cur);
  dists_from_centroid[v] = cur_dist;
  conn_verts.push_back(v);
  centroid_subtree[v] = subtree_idx;

  if (v != p) {
    bool changed = false;
    BestInfo my_info{cur_dist + weights[v], v};

    for (auto &x : bests) {
      if (x.SameType(my_info)) {
        changed = true;
        if (x.dist > my_info.dist)
          x = my_info;
        break;
      }
    }

    if (!changed) {
      bests.push_back(my_info);
      swap(*min_element(ALL(bests)), bests[0]);
      int lptr = 1;
      int seen[2] = {-1, 0};
      for (int i = 1; i < SZ(bests); ++i) {
        const bool same_group = groups[bests[i].vert] == groups[bests[0].vert];
        if (!same_group && bests[i].dist <= bests[1].dist) {
          bests[1] = bests[i];
          ++lptr;
        }
      }
      bests.resize(lptr);
    } else {
      // sort(ALL(bests));
    }

    if (centr_cur == 2)
      debug(v, bests, cur_dist, weights[v]);
  }

  for (auto &E : adj[v]) {
    const int s = E.st;
    if (s == p || layer_idx[s] < layer_idx[centr_cur]) {
      continue;
    }
    if (v == p) {
      subtree_idx = s;
    }
    DfsDists(s, v, cur_dist + E.nd, bests);
  }
}

void CentroidGroups() {
  fill_n(vert_ptr_dist, N + 1, (LL)1e18);

  for (int centroid = 1; centroid <= N; ++centroid) {
    best_dists[centroid].clear();
    subtree_idx = -1;
    centr_cur = centroid;
    conn_verts.clear();
    DfsDists(centroid, centroid, 0, best_dists[centroid]);
    debug(centroid, best_dists[centroid]);
    debug(conn_verts);

    for (int v : conn_verts) {
      for (auto &best : best_dists[centroid]) {
        if (groups[best.vert] == groups[v])
          continue;

        const LL new_dist = best.dist + dists_from_centroid[v] + weights[v];
        debug(centroid, v, dists_from_centroid[v], best.vert, new_dist);
        if (new_dist < vert_ptr_dist[v]) {
          vert_ptr[v] = best.vert;
          vert_ptr_dist[v] = new_dist;
        }
      }

      if (groups[centroid] != groups[v]) {
        const LL centr_dist =
            dists_from_centroid[v] + weights[v] + weights[centroid];
        if (centr_dist < vert_ptr_dist[v]) {
          vert_ptr[v] = centroid;
          vert_ptr_dist[v] = centr_dist;
        }
        if (centr_dist < vert_ptr_dist[centroid]) {
          vert_ptr[centroid] = v;
          vert_ptr_dist[centroid] = centr_dist;
        }
      }
    }
  }
}

int fu_parent[MaxN];

int FuFind(int v) {
  if (fu_parent[v] == v)
    return v;
  return fu_parent[v] = FuFind(fu_parent[v]);
}

bool FuUnion(int a, int b) {
  a = FuFind(a);
  b = FuFind(b);
  if (a != b) {
    fu_parent[a] = b;
    return true;
  }
  return false;
}

int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout << fixed << setprecision(11);
  cerr << fixed << setprecision(6);

  cin >> N;
  for (int i = 1; i <= N; ++i)
    cin >> weights[i];

  iota(fu_parent, fu_parent + N + 1, 0);

  for (int i = 0; i < N - 1; ++i) {
    int u, v, c;
    cin >> u >> v >> c;
    adj[u].emplace_back(v, c);
    adj[v].emplace_back(u, c);
  }

  fill_n(is_avail, N + 1, true);
  fill_n(layer_idx, N + 1, (int)1e9);
  Centroids(1, 0);

  int num_edges = 0;
  long long total_cost = 0;
  iota(groups, groups + N + 1, 0);

  while (num_edges < N - 1) {
    CentroidGroups();

    vector<int> order(N);
    vector<bool> had_out_edge(N + 1);
    iota(ALL(order), 1);
    sort(ALL(order), [&](int lhs, int rhs) {
      return vert_ptr_dist[lhs] < vert_ptr_dist[rhs];
    });

    for (int i : order) {
      if (had_out_edge[groups[i]]) {
        continue;
      }
      had_out_edge[groups[i]] = true;
      debug(i, vert_ptr[i], vert_ptr_dist[i]);
      assert(vert_ptr_dist[i] < 1e17);
      if (FuUnion(i, vert_ptr[i])) {
        total_cost += vert_ptr_dist[i];
        ++num_edges;
        debug("TAKING EDGE", i, vert_ptr[i], vert_ptr_dist[i],
              "!@#@!@!#@!##@!");
      }
    }

    for (int i = 1; i <= N; ++i) {
      groups[i] = FuFind(i);
      debug(i, groups[i]);
    }
  }

  cout << total_cost << "\\n";
}

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

#pragma GCC optimize("O3")

using namespace std;
#define PB push_back
#define MP make_pair
#define LL long long
// #define int LL
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define RE(i, n) FOR(i, 1, n)
#define REP(i, n) FOR(i, 0, (int)(n)-1)
#define R(i, n) REP(i, n)
#define VI vector<int>
#define PII pair<int, int>
#define LD long double
#define FI first
#define SE second
#define st FI
#define nd SE
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())

#define unordered_map __fast_unordered_map
template <class Key, class Value, class Hash = std::hash<Key>>
using unordered_map = __gnu_pbds::gp_hash_table<Key, Value, Hash>;

template <class C> void mini(C &a4, C b4) { a4 = min(a4, b4); }
template <class C> void maxi(C &a4, C b4) { a4 = max(a4, b4); }

template <class TH> void _dbg(const char *sdbg, TH h) {
  cerr << sdbg << '=' << h << endl;
}
template <class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
  while (*sdbg != ',')
    cerr << *sdbg++;
  cerr << '=' << h << ',';
  _dbg(sdbg + 1, a...);
}

template <class T> ostream &operator<<(ostream &os, vector<T> V) {
  os << "[";
  for (auto vv : V)
    os << vv << ",";
  return os << "]";
}
template <class L, class R> ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.st << "," << P.nd << ")";
}
template <class L, class R, class X>
ostream &operator<<(ostream &os, tuple<L, R, X> P) {
  return os << "(" << get<0>(P) << "," << get<1>(P) << "," << get<2>(P) << ")";
}

#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (__VA_ARGS__)
#define cerr                                                                   \\
  if (0)                                                                       \\
  cout
#endif

const int MaxN = 2e5 + 100;

int groups[MaxN];

struct BestInfo {
  LL dist;
  // int subtree_idx;
  int vert;

  bool operator<(const BestInfo &other) const { return dist < other.dist; }

  bool SameType(const BestInfo &other) const {
    return groups[vert] == groups[other.vert];
  }

  friend ostream &operator<<(ostream &os, const BestInfo &bi) {
    return os << "(" << bi.dist << "," << bi.vert << ")";
  }
};

vector<PII> adj[MaxN];
int weights[MaxN];
int N;
bool is_avail[MaxN];
int tree_size[MaxN];
int layer_idx[MaxN];
vector<int> conn_verts;

void DfsSizes(int v, int p) {
  tree_size[v] = 1;
  conn_verts.push_back(v);
  for (auto &E : adj[v]) {
    const int s = E.st;
    if (s == p) {
      continue;
    }
    if (!is_avail[s]) {
      continue;
    }
    DfsSizes(s, v);
    tree_size[v] += tree_size[s];
  }
}

void Centroids(int v, int layer) {
  conn_verts.clear();
  DfsSizes(v, v);

  int centroid = v;
  for (int s : conn_verts)
    if (2 * tree_size[s] >= tree_size[v] && tree_size[s] < tree_size[centroid])
      centroid = s;

  is_avail[centroid] = false;
  layer_idx[centroid] = layer;
  debug(centroid, layer);

  for (auto &E : adj[centroid])
    if (is_avail[E.st])
      Centroids(E.st, layer + 1);
}

const int kMaxBests = 4;
int subtree_idx;
int centr_cur;
LL dists_from_centroid[MaxN];
int vert_ptr[MaxN];
LL vert_ptr_dist[MaxN];
BestInfo best_non_centroid[MaxN][2];
BestInfo best_centroid[MaxN];

void DfsDists(int v, int p, LL cur_dist) {
  dists_from_centroid[v] = cur_dist;
  conn_verts.push_back(v);

  if (v != p) {
    BestInfo my_info{cur_dist + weights[v], v};

    if (groups[v] != groups[centr_cur]) {
      if (my_info < best_non_centroid[centr_cur][0]) {
        best_non_centroid[centr_cur][1] = best_non_centroid[centr_cur][0];
        best_non_centroid[centr_cur][0] = my_info;
      } else if (my_info < best_non_centroid[centr_cur][1]) {
        best_non_centroid[centr_cur][1] = my_info;
      }
    } else {
      mini(best_centroid[centr_cur], BestInfo{cur_dist + weights[v], v});
    }
  }

  for (auto &E : adj[v]) {
    const int s = E.st;
    if (s == p || layer_idx[s] < layer_idx[centr_cur]) {
      continue;
    }
    if (v == p) {
      subtree_idx = s;
    }
    DfsDists(s, v, cur_dist + E.nd);
  }
}

void CentroidGroups() {
  fill_n(vert_ptr_dist, N + 1, (LL)1e18);

  for (int centroid = 1; centroid <= N; ++centroid) {
    subtree_idx = -1;
    centr_cur = centroid;
    conn_verts.clear();
    best_non_centroid[centroid][0] = BestInfo{(LL)1e18, -1};
    best_non_centroid[centroid][1] = BestInfo{(LL)1e18, -1};
    best_centroid[centroid] = BestInfo{weights[centroid], centroid};
    DfsDists(centroid, centroid, 0);
    debug(conn_verts);

    for (int v : conn_verts) {
      for (int idx : {0, 1}) {
        const auto &best = best_non_centroid[centroid][idx];
        if (best.vert != -1 && groups[v] != groups[best.vert]) {
          const LL new_dist = best.dist + dists_from_centroid[v] + weights[v];
          if (new_dist < vert_ptr_dist[v]) {
            vert_ptr[v] = best.vert;
            vert_ptr_dist[v] = new_dist;
          }
        }
      }

      if (groups[centroid] != groups[v]) {
        const LL centr_dist =
            dists_from_centroid[v] + weights[v] + weights[centroid];
        const LL group_dist =
            dists_from_centroid[v] + best_centroid[centroid].dist + weights[v];
        if (group_dist < vert_ptr_dist[v]) {
          vert_ptr[v] = best_centroid[centroid].vert;
          vert_ptr_dist[v] = group_dist;
        }
        if (centr_dist < vert_ptr_dist[centroid]) {
          vert_ptr[centroid] = v;
          vert_ptr_dist[centroid] = centr_dist;
        }
      }
    }
  }
}

int fu_parent[MaxN];

int FuFind(int v) {
  if (fu_parent[v] == v)
    return v;
  return fu_parent[v] = FuFind(fu_parent[v]);
}

bool FuUnion(int a, int b) {
  a = FuFind(a);
  b = FuFind(b);
  if (a != b) {
    fu_parent[a] = b;
    return true;
  }
  return false;
}

int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout << fixed << setprecision(11);
  cerr << fixed << setprecision(6);

  cin >> N;
  for (int i = 1; i <= N; ++i)
    cin >> weights[i];

  iota(fu_parent, fu_parent + N + 1, 0);

  for (int i = 0; i < N - 1; ++i) {
    int u, v, c;
    cin >> u >> v >> c;
    adj[u].emplace_back(v, c);
    adj[v].emplace_back(u, c);
  }

  fill_n(is_avail, N + 1, true);
  fill_n(layer_idx, N + 1, (int)1e9);
  Centroids(1, 0);

  int num_edges = 0;
  long long total_cost = 0;
  iota(groups, groups + N + 1, 0);

  while (num_edges < N - 1) {
    CentroidGroups();

    vector<int> order(N);
    vector<bool> had_out_edge(N + 1);
    iota(ALL(order), 1);
    sort(ALL(order), [&](int lhs, int rhs) {
      return vert_ptr_dist[lhs] < vert_ptr_dist[rhs];
    });

    for (int i : order) {
      if (had_out_edge[groups[i]]) {
        continue;
      }
      had_out_edge[groups[i]] = true;
      debug(i, vert_ptr[i], vert_ptr_dist[i]);
      assert(vert_ptr_dist[i] < 1e17);
      if (FuUnion(i, vert_ptr[i])) {
        total_cost += vert_ptr_dist[i];
        ++num_edges;
        debug("TAKING EDGE", i, vert_ptr[i], vert_ptr_dist[i],
              "!@#@!@!#@!##@!");
      }
    }

    for (int i = 1; i <= N; ++i) {
      groups[i] = FuFind(i);
      debug(i, groups[i]);
    }
  }

  cout << total_cost << "\\n";
}


#include <bits/stdc++.h>

#define pb push_back
#define mp make_pair
#define taskname "A"

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> ii;

const int maxn = 2e5 + 5;
const int logn = log2(maxn) + 2;
const int mod = 1e9 + 7;
int lab[maxn];
int FindLab(int u) { return lab[u] < 0 ? u : lab[u] = FindLab(lab[u]); }
int n, cost[maxn];
struct node {
  pair<ll, int> a, b;
  node() { a = b = mp(1e18, -1); };
  void reset() { a = b = mp(1e18, -1); }
  void add(pair<ll, int> x, ll y = 0) {
    x.first += y;
    if (a.second == x.second)
      a = min(a, x);
    else if (b.second == x.second)
      b = min(b, x);
    else if (a > x)
      b = a, a = x;
    else if (b > x)
      b = x;
    if (b < a)
      swap(a, b);
    assert(b.second != a.second || a.second == -1);
  }
} dp[maxn];
pair<ll, int> bezt[maxn];
vector<ii> adj[maxn];

node dfs(int u, int par) {
  node a;
  //    cout << u << endl;
  for (auto c : adj[u]) {
    if (c.first == par)
      continue;
    auto tmp = dfs(c.first, u);
    a.add(tmp.a, c.second);
    a.add(tmp.b, c.second);
  }
  if (a.a.second != FindLab(u))
    bezt[FindLab(u)] =
        min(bezt[FindLab(u)], mp(a.a.first + cost[u], a.a.second));
  if (a.b.second != FindLab(u))
    bezt[FindLab(u)] =
        min(bezt[FindLab(u)], mp(a.b.first + cost[u], a.b.second));
  a.add(mp(cost[u], FindLab(u)));
  for (auto c : adj[u]) {
    if (c.first == par)
      continue;
    dp[c.first].add(a.a);
    dp[c.first].add(a.b);
  }
  return a;
}

void dfs1(int u, int par, node a) {
  if (a.a.second != FindLab(u))
    bezt[FindLab(u)] =
        min(bezt[FindLab(u)], mp(a.a.first + cost[u], a.a.second));
  if (a.b.second != FindLab(u))
    bezt[FindLab(u)] =
        min(bezt[FindLab(u)], mp(a.b.first + cost[u], a.b.second));
  for (auto c : adj[u]) {
    if (c.first == par)
      continue;
    node b;
    b.add(a.a, c.second);
    b.add(a.b, c.second);
    b.add(dp[c.first].a, c.second);
    b.add(dp[c.first].b, c.second);
    dfs1(c.first, u, b);
  }
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  if (fopen(taskname ".INP", "r")) {
    freopen(taskname ".INP", "r", stdin);
    freopen(taskname ".OUT", "w", stdout);
  }
  fill_n(lab, maxn, -1);
  cin >> n;
  for (int i = 1; i <= n; ++i)
    cin >> cost[i];
  for (int i = 1; i < n; ++i) {
    int u, v, c;
    cin >> u >> v >> c;
    adj[u].pb(mp(v, c));
    adj[v].pb(mp(u, c));
  }
  ll res = 0;
  int cnt = n - 1;
  while (cnt > 0) {
    for (int i = 1; i <= n; ++i)
      dp[i].reset(), bezt[i] = mp(1e18, -1);
    dfs(1, 0);
    //        return 0;
    node tmp;
    tmp.reset();
    dfs1(1, 0, tmp);
    vector<pair<ll, ii>> edge;
    for (int i = 1; i <= n; ++i) {
      if (lab[i] < 0) {
        if (bezt[i].first < 1e18) {
          edge.pb(mp(bezt[i].first, mp(i, bezt[i].second)));
          int u = i, v = bezt[i].second;
          if (u == v)
            continue;
          res += bezt[i].first;
          if (lab[u] > lab[v])
            swap(u, v);
          lab[u] += lab[v];
          lab[v] = u;
          --cnt;
        }
      }
    }
  }
  cout << res;
}

#include <bits/stdc++.h>

#define pb push_back
#define mp make_pair
#define taskname "A"

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> ii;

const int maxn = 2e5 + 5;
const int logn = log2(maxn) + 2;
const int mod = 1e9 + 7;
int lab[maxn];
int FindLab(int u) { return lab[u] < 0 ? u : lab[u] = FindLab(lab[u]); }
int n, cost[maxn];
struct node {
  pair<ll, int> a, b;
  node() { a = b = mp(1e18, -1); };
  void reset() { a = b = mp(1e18, -1); }
  void add(pair<ll, int> x, ll y = 0) {
    x.first += y;
    if (a.second == x.second)
      a = min(a, x);
    else if (b.second == x.second)
      b = min(b, x);
    else if (a > x)
      b = a, a = x;
    else if (b > x)
      b = x;
    if (b < a)
      swap(a, b);
    assert(b.second != a.second || a.second == -1);
  }
} dp[maxn];
pair<ll, int> bezt[maxn];
vector<ii> adj[maxn];

node dfs(int u, int par) {
  node a;
  //    cout << u << endl;
  for (auto c : adj[u]) {
    if (c.first == par)
      continue;
    auto tmp = dfs(c.first, u);
    a.add(tmp.a, c.second);
    a.add(tmp.b, c.second);
  }
  if (a.a.second != FindLab(u))
    bezt[FindLab(u)] =
        min(bezt[FindLab(u)], mp(a.a.first + cost[u], a.a.second));
  if (a.b.second != FindLab(u))
    bezt[FindLab(u)] =
        min(bezt[FindLab(u)], mp(a.b.first + cost[u], a.b.second));
  a.add(mp(cost[u], FindLab(u)));
  for (auto c : adj[u]) {
    if (c.first == par)
      continue;
    dp[c.first].add(a.a);
    dp[c.first].add(a.b);
  }
  return a;
}

void dfs1(int u, int par, node a) {
  if (a.a.second != FindLab(u))
    bezt[FindLab(u)] =
        min(bezt[FindLab(u)], mp(a.a.first + cost[u], a.a.second));
  if (a.b.second != FindLab(u))
    bezt[FindLab(u)] =
        min(bezt[FindLab(u)], mp(a.b.first + cost[u], a.b.second));
  for (auto c : adj[u]) {
    if (c.first == par)
      continue;
    node b;
    b.add(a.a, c.second);
    b.add(a.b, c.second);
    b.add(dp[c.first].a, c.second);
    b.add(dp[c.first].b, c.second);
    dfs1(c.first, u, b);
  }
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  if (fopen(taskname ".INP", "r")) {
    freopen(taskname ".INP", "r", stdin);
    freopen(taskname ".OUT", "w", stdout);
  }
  fill_n(lab, maxn, -1);
  cin >> n;
  for (int i = 1; i <= n; ++i)
    cin >> cost[i];
  for (int i = 1; i < n; ++i) {
    int u, v, c;
    cin >> u >> v >> c;
    adj[u].pb(mp(v, c));
    adj[v].pb(mp(u, c));
  }
  ll res = 0;
  int cnt = n - 1;
  while (cnt > 0) {
    for (int i = 1; i <= n; ++i)
      dp[i].reset(), bezt[i] = mp(1e18, -1);
    dfs(1, 0);
    //        return 0;
    node tmp;
    tmp.reset();
    dfs1(1, 0, tmp);
    vector<pair<ll, ii>> edge;
    for (int i = 1; i <= n; ++i) {
      if (lab[i] < 0) {
        if (bezt[i].first < 1e18) {
          edge.pb(mp(bezt[i].first, mp(i, bezt[i].second)));
          int u = FindLab(i), v = FindLab(bezt[i].second);
          if (u == v)
            continue;
          res += bezt[i].first;
          if (lab[u] > lab[v])
            swap(u, v);
          lab[u] += lab[v];
          lab[v] = u;
          --cnt;
        }
      }
    }
  }
  cout << res;
}


#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>

#define pb push_back
#define mp make_pair

using namespace std;

template <typename T> inline bool upmin(T &x, T y) {
  return y < x ? x = y, 1 : 0;
}

typedef unsigned int u32;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double lod;
typedef pair<int, int> PR;
typedef vector<int> VI;

const lod pi = acos(-1);
const int oo = 1 << 30;
const LL OO = 1e18;

const int N = 2e5 + 100;

int gi() {
  int w = 0;
  bool q = 1;
  char c = getchar();
  while ((c < '0' || c > '9') && c != '-')
    c = getchar();
  if (c == '-')
    q = 0, c = getchar();
  while (c >= '0' && c <= '9')
    w = w * 10 + c - '0', c = getchar();
  return q ? w : -w;
}

int val[N], fa[N];
int head[N], nxt[N * 2], to[N * 2], w[N * 2];
inline int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
#define fi first
#define se second
struct DT {
  pair<LL, int> fi, se;
} f[N];
inline DT operator+(const DT &a, const int &b) {
  return (DT){mp(a.fi.fi + b, a.fi.se), mp(a.se.fi + b, a.se.se)};
}
inline DT operator+(const DT &a, const DT &b) {
  DT ans;
  if (a.fi.se == b.fi.se)
    ans.fi = min(a.fi, b.fi), ans.se = min(a.se, b.se);
  else if (a.fi.fi < b.fi.fi)
    ans = a, upmin(ans.se, b.fi);
  else
    ans = b, upmin(ans.se, a.fi);
  return ans;
}
inline void dfs1(int k, int fa) {
  f[k] = (DT){mp(val[k], find(k)), mp(OO, 0)};
  for (int i = head[k]; i; i = nxt[i])
    if (to[i] != fa)
      dfs1(to[i], k), f[k] = f[k] + (f[to[i]] + w[i]);
}
inline void dfs2(int k, int fa) {
  for (int i = head[k]; i; i = nxt[i])
    if (to[i] != fa) {
      f[to[i]] = f[to[i]] + (f[k] + w[i]);
      dfs2(to[i], k);
    }
}
int main() {
#ifndef ONLINE_JUDGE
  freopen("J.in", "r", stdin);
  freopen("J.out", "w", stdout);
#endif
  int n = gi(), i, a, b, C = n, tot = 0;
  pair<LL, int> p;
  LL ans = 0;
  for (i = 1; i <= n; i++)
    val[i] = gi(), fa[i] = i;
  for (i = 1; i < n; i++) {
    a = gi(), b = gi();
    to[++tot] = b, nxt[tot] = head[a], head[a] = tot;
    to[++tot] = a, nxt[tot] = head[b], head[b] = tot;
    w[tot] = w[tot - 1] = gi();
  }
  while (C > 1) {
    dfs1(1, 0);
    dfs2(1, 0);
    for (i = 1; i <= n; i++)
      f[i].fi.fi += val[i], f[i].se.fi += val[i];
    for (i = 1; i <= n; i++)
      if (fa[i] != i)
        f[find(i)] = f[find(i)] + f[i];
    for (i = 1; i <= n; i++)
      if (fa[i] == i) {
        p = f[i].fi.se == i ? f[i].se : f[i].fi;
        if (find(i) != find(p.se)) {
          ans += p.fi;
          fa[i] = p.se;
          C--;
        }
      }
  }
  cout << ans << endl;
  return 0;
}

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>

#define pb push_back
#define mp make_pair

using namespace std;

template <typename T> inline bool upmin(T &x, T y) {
  return y < x ? x = y, 1 : 0;
}

typedef unsigned int u32;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double lod;
typedef pair<int, int> PR;
typedef vector<int> VI;

const lod pi = acos(-1);
const int oo = 1 << 30;
const LL OO = 1e18;

const int N = 2e5 + 100;

int gi() {
  int w = 0;
  bool q = 1;
  char c = getchar();
  while ((c < '0' || c > '9') && c != '-')
    c = getchar();
  if (c == '-')
    q = 0, c = getchar();
  while (c >= '0' && c <= '9')
    w = w * 10 + c - '0', c = getchar();
  return q ? w : -w;
}

int val[N], fa[N];
int head[N], nxt[N * 2], to[N * 2], w[N * 2];
inline int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
#define fi first
#define se second
struct DT {
  pair<LL, int> fi, se;
} f[N];
inline DT operator+(const DT &a, const int &b) {
  return (DT){mp(a.fi.fi + b, a.fi.se), mp(a.se.fi + b, a.se.se)};
}
inline DT operator+(const DT &a, const DT &b) {
  DT ans;
  if (a.fi.se == b.fi.se)
    ans.fi = min(a.fi, b.fi), ans.se = min(a.se, b.se);
  else if (a.fi.fi < b.fi.fi)
    ans = a, upmin(ans.se, b.fi);
  else
    ans = b, upmin(ans.se, a.fi);
  return ans;
}
inline void dfs1(int k, int fa) {
  f[k] = (DT){mp(val[k], find(k)), mp(OO, 0)};
  for (int i = head[k]; i; i = nxt[i])
    if (to[i] != fa)
      dfs1(to[i], k), f[k] = f[k] + (f[to[i]] + w[i]);
}
inline void dfs2(int k, int fa) {
  for (int i = head[k]; i; i = nxt[i])
    if (to[i] != fa) {
      f[to[i]] = f[to[i]] + (f[k] + w[i]);
      dfs2(to[i], k);
    }
}
int main() {
  int n = gi(), i, a, b, C = n, tot = 0;
  pair<LL, int> p;
  LL ans = 0;
  for (i = 1; i <= n; i++)
    val[i] = gi(), fa[i] = i;
  for (i = 1; i < n; i++) {
    a = gi(), b = gi();
    to[++tot] = b, nxt[tot] = head[a], head[a] = tot;
    to[++tot] = a, nxt[tot] = head[b], head[b] = tot;
    w[tot] = w[tot - 1] = gi();
  }
  while (C > 1) {
    dfs1(1, 0);
    dfs2(1, 0);
    for (i = 1; i <= n; i++)
      f[i].fi.fi += val[i], f[i].se.fi += val[i];
    for (i = 1; i <= n; i++)
      if (fa[i] != i)
        f[find(i)] = f[find(i)] + f[i];
    for (i = 1; i <= n; i++)
      if (fa[i] == i) {
        p = f[i].fi.se == i ? f[i].se : f[i].fi;
        if (find(i) != find(p.se)) {
          ans += p.fi;
          fa[i] = p.se;
          C--;
        }
      }
  }
  cout << ans << endl;
  return 0;
}


#include <algorithm>
#include <functional>
#include <inttypes.h>
#include <queue>
#include <stdint.h>
#include <stdio.h>

int ri() {
  int n;
  scanf("%d", &n);
  return n;
}

#define INF 1000000000000000000

struct Node;
extern Node *NONE;
struct Node {
  template <class T> struct Min {
    std::priority_queue<T, std::vector<T>, std::greater<T>> all;
    std::priority_queue<T, std::vector<T>, std::greater<T>> removing;
    void add(T content) { all.push(content); }
    void fix() {
      while (removing.size() && removing.top() == all.top())
        removing.pop(), all.pop();
    }
    void remove(T content) {
      removing.push(content);
      fix();
    }
    T min() { return all.size() ? all.top() : T{INF, {}}; }
    int size() { return all.size() - removing.size(); }
  };
#define l ch[0]
#define r ch[1]
  Node *ch[2] = {NONE, NONE};
  Node *p = NONE;
  /* vvvv   LIGHT stuff   vvvv */
  Min<std::pair<int64_t, int>> light_nearest[2];
  Min<std::pair<int64_t, std::pair<int, int>>> light_res;
  /* vvvv   self stuff   vvvv */
  bool rev = false;
  bool marked[2] = {false, false};
  int len = 0;
  int id = -1;
  /* vvvv   heavy stuff   vvvv */
  int64_t len_sum = 0;
  std::pair<int64_t, std::pair<int, int>> res = {INF, {-1, -1}};
  std::pair<int64_t, int> left[2] = {{INF, -1}, {INF, -1}};
  std::pair<int64_t, int> right[2] = {{INF, -1}, {INF, -1}};
  Node *fetch() {
    if (l != NONE)
      l->flush();
    if (r != NONE)
      r->flush();
    len_sum = len + l->len_sum + r->len_sum;
    // a lot of candidates
    res = {INF, {-1, -1}};
    if (light_res.size())
      res = light_res.min(); // inside light
    res = std::min(
        res, {light_nearest[0].min().first + light_nearest[1].min().first + len,
              {light_nearest[0].min().second,
               light_nearest[1].min().second}}); // light to light
    if (marked[0]) {                             // from this
      res = std::min(
          res, {l->right[1].first, {id, l->right[1].second}}); // heavy left
      res = std::min(
          res, {r->left[1].first, {id, r->left[1].second}}); // heavy right
      res = std::min(res, {light_nearest[1].min().first,
                           {id, light_nearest[1].min().second}}); // light
    }
    if (marked[1]) { // from this
      res = std::min(
          res, {l->right[0].first, {l->right[0].second, id}}); // heavy left
      res = std::min(
          res, {r->left[0].first, {r->left[0].second, id}}); // heavy right
      res = std::min(res, {light_nearest[0].min().first,
                           {light_nearest[0].min().second, id}}); // light
    }
    // left to right
    res = std::min(res, {l->right[0].first + r->left[1].first + len,
                         {l->right[0].second, r->left[1].second}});
    res = std::min(res, {l->right[1].first + r->left[0].first + len,
                         {r->left[0].second, l->right[1].second}});
    // light to left/right
    res = std::min(res, {l->right[0].first + light_nearest[1].min().first + len,
                         {l->right[0].second, light_nearest[1].min().second}});
    res = std::min(res, {r->left[0].first + light_nearest[1].min().first + len,
                         {r->left[0].second, light_nearest[1].min().second}});
    res = std::min(res, {l->right[1].first + light_nearest[0].min().first + len,
                         {light_nearest[0].min().second, l->right[1].second}});
    res = std::min(res, {r->left[1].first + light_nearest[0].min().first + len,
                         {light_nearest[0].min().second, r->left[1].second}});
    res = std::min({res, l->res, r->res}); // inside heavy left/right

    for (int i = 0; i < 2; i++) {
      left[i] =
          std::min({l->left[i],
                    {r->left[i].first + len + l->len_sum, r->left[i].second},
                    {light_nearest[i].min().first + len + l->len_sum,
                     light_nearest[i].min().second}});
      if (marked[i])
        left[i] = std::min(left[i], {l->len_sum, id});
      right[i] =
          std::min({r->right[i],
                    {l->right[i].first + len + r->len_sum, l->right[i].second},
                    {light_nearest[i].min().first + len + r->len_sum,
                     light_nearest[i].min().second}});
      if (marked[i])
        right[i] = std::min(right[i], {r->len_sum, id});
    }
    return this;
  }
  Node *flush() {
    if (rev) {
      std::swap(l, r);
      l->rev ^= 1;
      r->rev ^= 1;
      std::swap(left[0], right[0]);
      std::swap(left[1], right[1]);
      rev = false;
    }
    return this;
  }
  Node *rotate(int dir) {
    Node *new_root = ch[!dir];
    ch[!dir] = new_root->ch[dir];
    ch[!dir]->p = this;
    new_root->ch[dir] = this;
    new_root->p = p;
    if (p->l == this)
      p->l = new_root;
    if (p->r == this)
      p->r = new_root;
    p = new_root;
    return fetch(), new_root->fetch();
  }
  bool is_root() { return p == NONE || (p->l != this && p->r != this); }
  void splay() {
    flush();
    while (!is_root()) {
      if (p->is_root()) {
        p->flush(), flush();
        p->rotate(p->l == this);
      } else {
        Node *pp = p->p;
        pp->flush(), p->flush(), flush();
        bool flag0 = pp->l == p;
        bool flag1 = p->l == this;
        if (flag0 == flag1)
          pp->rotate(flag0);
        p->rotate(flag1);
        if (flag0 != flag1)
          pp->rotate(flag0);
      }
    }
  }
  Node *expose() {
    Node *prev = NONE;
    for (Node *cur = this; cur != NONE; cur = cur->p) {
      cur->splay();
      if (cur->r != NONE) { // add
        cur->r->flush();
        for (int i = 0; i < 2; i++)
          cur->light_nearest[i].add(cur->r->left[i]);
        cur->light_res.add(cur->r->res);
      }
      cur->r = prev;
      if (cur->r != NONE) { // remove
        for (int i = 0; i < 2; i++)
          cur->light_nearest[i].remove(cur->r->left[i]);
        cur->light_res.remove(cur->r->res);
      }
      cur->fetch();
      prev = cur;
    }
    splay();
    return prev;
  }
  void link(Node *parent) {
    expose();
    parent->expose();
    p = parent;
    parent->r = this;
    parent->fetch();
  }
  void cut() {
    expose();
    l->p = NONE;
    l = NONE;
    fetch();
  }
  void evert() {
    expose();
    rev = true;
    flush();
  }
#undef l
#undef r
};
Node *NONE = new Node;

int main() {
  int n = ri();
  int a[n];
  for (auto &i : a)
    i = ri();
  Node nodes[2 * n];
  Node edges[2 * n - 1];
  for (int i = 0; i < 2 * n; i++) {
    nodes[i].id = i;
    if (i >= n)
      nodes[i].marked[1] = true;
    nodes[i].fetch();
  }
  for (int i = 0; i + 1 < n; i++) {
    int a = ri() - 1;
    int b = ri() - 1;
    int c = ri();
    edges[i].len = c;
    edges[i].fetch();
    nodes[a].evert();
    nodes[a].link(edges + i);
    edges[i].link(nodes + b);
  }
  for (int i = 0; i < n; i++) {
    edges[i + n - 1].len = a[i];
    edges[i + n - 1].fetch();
    edges[i + n - 1].link(nodes + i);
    nodes[i + n].link(edges + i + n - 1);
  }
  auto flip = [&](int i) {
    nodes[i].expose();
    nodes[i].marked[1] = false;
    nodes[i].marked[0] = true;
    nodes[i].fetch();
  };
  flip(n);
  int64_t res = 0;
  for (int i = 0; i + 1 < n; i++) {
    nodes[0].evert();
    res += nodes[0].res.first;
    flip(nodes[0].res.second.second);
  }
  printf("%" PRId64 "\\n", res);
  return 0;
}

#include <algorithm>
#include <functional>
#include <inttypes.h>
#include <queue>
#include <stdint.h>
#include <stdio.h>

int ri() {
  int n;
  scanf("%d", &n);
  return n;
}

#define INF 1000000000000000000

struct Node;
extern Node *NONE;
struct Node {
  template <class T> struct Min {
    std::priority_queue<T, std::vector<T>, std::greater<T>> all;
    std::priority_queue<T, std::vector<T>, std::greater<T>> removing;
    void add(T content) { all.push(content); }
    void fix() {
      while (removing.size() && removing.top() == all.top())
        removing.pop(), all.pop();
    }
    void remove(T content) {
      removing.push(content);
      fix();
    }
    T min() { return all.size() ? all.top() : T{INF, {}}; }
    int size() { return all.size() - removing.size(); }
  };
#define l ch[0]
#define r ch[1]
  Node *ch[2] = {NONE, NONE};
  Node *p = NONE;
  /* vvvv   LIGHT stuff   vvvv */
  Min<std::pair<int64_t, int>> light_nearest[2];
  Min<std::pair<int64_t, std::pair<int, int>>> light_res;
  /* vvvv   self stuff   vvvv */
  bool rev = false;
  bool marked[2] = {false, false};
  int len = 0;
  int id = -1;
  int bias = 0;
  /* vvvv   heavy stuff   vvvv */
  int64_t len_sum = 0;
  std::pair<int64_t, std::pair<int, int>> res = {INF, {-1, -1}};
  std::pair<int64_t, int> left[2] = {{INF, -1}, {INF, -1}};
  std::pair<int64_t, int> right[2] = {{INF, -1}, {INF, -1}};
  Node *fetch() {
    if (l != NONE)
      l->flush();
    if (r != NONE)
      r->flush();
    len_sum = len + l->len_sum + r->len_sum;
    // a lot of candidates
    res = {INF, {-1, -1}};
    if (light_res.size())
      res = light_res.min(); // inside light
    res = std::min(
        res, {light_nearest[0].min().first + light_nearest[1].min().first + len,
              {light_nearest[0].min().second,
               light_nearest[1].min().second}}); // light to light
    if (marked[0]) {                             // from this
      res = std::min(res, {l->right[1].first + bias,
                           {id, l->right[1].second}}); // heavy left
      res = std::min(res, {r->left[1].first + bias,
                           {id, r->left[1].second}}); // heavy right
      res = std::min(res, {light_nearest[1].min().first + bias,
                           {id, light_nearest[1].min().second}}); // light
    }
    if (marked[1]) { // from this
      res = std::min(res, {l->right[0].first + bias,
                           {l->right[0].second, id}}); // heavy left
      res = std::min(res, {r->left[0].first + bias,
                           {r->left[0].second, id}}); // heavy right
      res = std::min(res, {light_nearest[0].min().first + bias,
                           {light_nearest[0].min().second, id}}); // light
    }
    // left to right
    res = std::min(res, {l->right[0].first + r->left[1].first + len,
                         {l->right[0].second, r->left[1].second}});
    res = std::min(res, {l->right[1].first + r->left[0].first + len,
                         {r->left[0].second, l->right[1].second}});
    // light to left/right
    res = std::min(res, {l->right[0].first + light_nearest[1].min().first + len,
                         {l->right[0].second, light_nearest[1].min().second}});
    res = std::min(res, {r->left[0].first + light_nearest[1].min().first + len,
                         {r->left[0].second, light_nearest[1].min().second}});
    res = std::min(res, {l->right[1].first + light_nearest[0].min().first + len,
                         {light_nearest[0].min().second, l->right[1].second}});
    res = std::min(res, {r->left[1].first + light_nearest[0].min().first + len,
                         {light_nearest[0].min().second, r->left[1].second}});
    res = std::min({res, l->res, r->res}); // inside heavy left/right

    for (int i = 0; i < 2; i++) {
      left[i] =
          std::min({l->left[i],
                    {r->left[i].first + len + l->len_sum, r->left[i].second},
                    {light_nearest[i].min().first + len + l->len_sum,
                     light_nearest[i].min().second}});
      if (marked[i])
        left[i] = std::min(left[i], {l->len_sum + bias, id});
      right[i] =
          std::min({r->right[i],
                    {l->right[i].first + len + r->len_sum, l->right[i].second},
                    {light_nearest[i].min().first + len + r->len_sum,
                     light_nearest[i].min().second}});
      if (marked[i])
        right[i] = std::min(right[i], {r->len_sum + bias, id});
    }
    return this;
  }
  Node *flush() {
    if (rev) {
      std::swap(l, r);
      l->rev ^= 1;
      r->rev ^= 1;
      std::swap(left[0], right[0]);
      std::swap(left[1], right[1]);
      rev = false;
    }
    return this;
  }
  Node *rotate(int dir) {
    Node *new_root = ch[!dir];
    ch[!dir] = new_root->ch[dir];
    ch[!dir]->p = this;
    new_root->ch[dir] = this;
    new_root->p = p;
    if (p->l == this)
      p->l = new_root;
    if (p->r == this)
      p->r = new_root;
    p = new_root;
    return fetch(), new_root->fetch();
  }
  bool is_root() { return p == NONE || (p->l != this && p->r != this); }
  void splay() {
    flush();
    while (!is_root()) {
      if (p->is_root()) {
        p->flush(), flush();
        p->rotate(p->l == this);
      } else {
        Node *pp = p->p;
        pp->flush(), p->flush(), flush();
        bool flag0 = pp->l == p;
        bool flag1 = p->l == this;
        if (flag0 == flag1)
          pp->rotate(flag0);
        p->rotate(flag1);
        if (flag0 != flag1)
          pp->rotate(flag0);
      }
    }
  }
  Node *expose() {
    Node *prev = NONE;
    for (Node *cur = this; cur != NONE; cur = cur->p) {
      cur->splay();
      if (cur->r != NONE) { // add
        cur->r->flush();
        for (int i = 0; i < 2; i++)
          cur->light_nearest[i].add(cur->r->left[i]);
        cur->light_res.add(cur->r->res);
      }
      cur->r = prev;
      if (cur->r != NONE) { // remove
        for (int i = 0; i < 2; i++)
          cur->light_nearest[i].remove(cur->r->left[i]);
        cur->light_res.remove(cur->r->res);
      }
      cur->fetch();
      prev = cur;
    }
    splay();
    return prev;
  }
  void link(Node *parent) {
    expose();
    parent->expose();
    p = parent;
    parent->r = this;
    parent->fetch();
  }
  void cut() {
    expose();
    l->p = NONE;
    l = NONE;
    fetch();
  }
  void evert() {
    expose();
    rev = true;
    flush();
  }
#undef l
#undef r
};
Node *NONE = new Node;

int main() {
  int n = ri();
  int a[n];
  for (auto &i : a)
    i = ri();
  Node nodes[n];
  Node edges[n - 1];
  for (int i = 0; i < n; i++) {
    nodes[i].id = i;
    nodes[i].marked[1] = true;
    nodes[i].bias = a[i];
    nodes[i].fetch();
  }
  for (int i = 0; i + 1 < n; i++) {
    int a = ri() - 1;
    int b = ri() - 1;
    int c = ri();
    edges[i].len = c;
    edges[i].fetch();
    nodes[a].evert();
    nodes[a].link(edges + i);
    edges[i].link(nodes + b);
  }
  auto flip = [&](int i) {
    nodes[i].expose();
    nodes[i].marked[1] = false;
    nodes[i].marked[0] = true;
    nodes[i].fetch();
  };
  flip(0);
  int64_t res = 0;
  for (int i = 0; i + 1 < n; i++) {
    nodes[0].evert();
    res += nodes[0].res.first;
    flip(nodes[0].res.second.second);
  }
  printf("%" PRId64 "\\n", res);
  return 0;
}