#include #define fi first #define se second #define rep(i,s,n) for (int i = (s); i < (n); ++i) #define rrep(i,n,g) for (int i = (n)-1; i >= (g); --i) #define all(a) a.begin(),a.end() #define rall(a) a.rbegin(),a.rend() #define len(x) (int)(x).size() #define dup(x,y) (((x)+(y)-1)/(y)) #define pb push_back #define eb emplace_back #define Field(T) vector> using namespace std; using ll = long long; using ull = unsigned long long; template using pq = priority_queue,greater>; using P = pair; templatebool chmax(T&a,T b){if(abool chmin(T&a,T b){if(b par; vector siz; int cnt; UnionFind(int sz_): par(sz_), siz(sz_, 1), cnt(sz_) { for (int i = 0; i < sz_; ++i) par[i] = i; } void init(int sz_) { par.resize(sz_); siz.assign(sz_, 1); for (int i = 0; i < sz_; ++i) par[i] = i; } int root(int x) { while (par[x] != x) { x = par[x] = par[par[x]]; } return x; } bool merge(int x, int y) { x = root(x); y = root(y); if (x == y) return false; if (siz[x] < siz[y]) swap(x, y); siz[x] += siz[y]; par[y] = x; --cnt; return true; } bool issame(int x, int y) { return root(x) == root(y); } int size(int x) { return siz[root(x)]; } int group_siz() { return cnt; } }; template struct MaxFlow { struct edge { int to; T cap; int rev; bool is_rev; }; vector> G; vector dist, iter; MaxFlow() = default; explicit MaxFlow(int n) : G(n) {} void add_edge(int from, int to, T cap = 1) { G[from].emplace_back(edge{to, cap, (int)G[to].size(), 0}); G[to].emplace_back(edge{from, 0, (int)G[from].size()-1, 1}); } void debug() { for (int i = 0; i < (int)G.size(); ++i) { for (edge &e : G[i]) { if (e.is_rev) continue; edge &rev_e = G[e.to][e.rev]; cout << i << " -> " << e.to << " : " << "(" << rev_e.cap << "/" << e.cap + rev_e.cap << ")" << endl; } } } void bfs(const int &s) { dist.assign(G.size(), -1); dist[s] = 0; queue que; que.push(s); while(!que.empty()) { int v = que.front(); que.pop(); for (edge &e : G[v]) { if (e.cap == 0 || dist[e.to] >= 0) continue; dist[e.to] = dist[v] + 1; que.push(e.to); } } } T dfs(int v, const int &t, T f) { if (v == t) return f; T ret = 0; for (int& i = iter[v]; i < (int)G[v].size(); ++i) { edge& e = G[v][i]; if (e.cap == 0 || dist[v] >= dist[e.to]) continue; T d = dfs(e.to, t, min(f - ret, e.cap)); if (d == 0) continue; e.cap -= d; G[e.to][e.rev].cap += d; ret += d; if (f == ret) break; } return ret; } T flow(int s, int t, T f_limit = numeric_limits::max()) { T ret = 0; queue que; while(true) { bfs(s); if (dist[t] == -1) break; iter.assign(G.size(), 0); while(ret < f_limit) { T f = dfs(s, t, f_limit - ret); if (f == 0) break; ret += f; } } return ret; } vector min_cut(int s) { vector used(G.size(), 0); used[s] = 1; queue que; que.push(s); while(!que.empty()) { int v = que.front(); que.pop(); for (edge &e : G[v]) { if (e.cap > 0 && !used[e.to]) { used[e.to] = 1; que.push(e.to); } } } return used; } }; template struct BurnySolver { using table = array; int n; T a = T(0); vector b, c; map, table> d; vector flip; MaxFlow G; BurnySolver(int n): n(n), b(n), c(n), flip(n, -1) { G = MaxFlow(n+2); } // f == 1 -> s, f == 0 -> t void add_constraint(int i, bool f, T cost) { (f ? b[i] : c[i]) += cost; } // f == 1 -> s, f == 0 -> t void add_constraint(int i, bool fx, int j, bool fy, T cost) { if (i > j) { swap(i, j); swap(fx, fy); } d[{i, j}][2*fx+fy] += cost; } // bool == 0 -> infeasible, bool == 1 -> solved pair solve() { UnionFind uf(n*2); for (auto& e: d) { int i, j; tie(i, j) = e.first; const auto& t = e.second; T s = -t[0] + t[1] + t[2] - t[3]; if (s < 0) { uf.merge(i, j+n); uf.merge(i+n, j); } else if (s > 0) { uf.merge(i, j); uf.merge(i+n, j+n); } } for (int i = 0; i < n; ++i) { if (uf.issame(i, i+n)) { return {0, 0}; } if (flip[i] != -1) continue; int x = uf.root(i); int y = uf.root(i+n); if (flip[x%n] != -1) { flip[i] = int(x >= n); } else if (flip[y%n] != -1) { flip[i] = int(y < n); } else { flip[i] = 0; flip[x%n] = int(x >= n); } } for(auto &e: d) { int i, j; tie(i, j) = e.first; auto& t = e.second; if (flip[i]) { swap(t[0], t[2]); swap(t[1], t[3]); } if (flip[j]) { swap(t[0], t[1]); swap(t[2], t[3]); } T s = -t[0] + t[1] + t[2] - t[3]; a += t[0]; (flip[i] ? c[i] : b[i]) += t[2] - t[0]; (flip[j] ? c[j] : b[j]) += t[3] - t[2]; t[1] = s; t[0] = t[2] = t[3] = 0; assert(s >= 0); } for (int i = 0; i < n; ++i) { if (flip[i]) { swap(b[i], c[i]); } if (b[i] >= c[i]) { a += c[i]; b[i] -= c[i]; c[i] = 0; } else { a += b[i]; c[i] -= b[i]; b[i] = 0; } } for (int i = 0; i < n; ++i) { if (b[i] > 0) { G.add_edge(i, n+1, b[i]); } if (c[i] > 0) { G.add_edge(n, i, c[i]); } } for (auto& e: d) { int i, j; tie(i, j) = e.first; const auto& t = e.second; if (t[2] > 0) { G.add_edge(i, j, t[2]); } if (t[1] > 0) { G.add_edge(j, i, t[1]); } } return {a + G.flow(n, n+1), 1}; } vector restore() { vector ret = G.min_cut(n); rep(i,0,n) { if (flip[i]) { ret[i] = 1 - ret[i]; } } return ret; } }; static constexpr ll inf = 1000000000000000; int main() { int n; cin >> n; BurnySolver bs(n); rep(i,0,n) { int p; cin >> p; bs.add_constraint(i, 1, -p); } int m; cin >> m; rep(i,0,m) { int u, v; cin >> u >> v; --u, --v; bs.add_constraint(u, 0, v, 1, inf); } int k; cin >> k; rep(i,0,k) { int a, b, s; cin >> a >> b >> s; --a, --b; bs.add_constraint(a, 1, b, 1, -s); } cout << -bs.solve().fi << endl; return 0; }