#include #define fi first #define se second #define rep(i,s,n) for (int i = (s); i < (n); ++i) #define rrep(i,g,n) 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 struct edge { int src, to; T cost; edge(int to, T cost) : src(-1), to(to), cost(cost) {} edge(int src, int to, T cost) : src(src), to(to), cost(cost) {} edge &operator=(const int &x) { to = x; return *this; } operator int() const { return to; } }; template< typename T > using Edges = vector< edge< T > >; template< typename T > using WeightedGraph = vector< Edges< T > >; using UnWeightedGraph = vector< vector< int > >; template< typename T > using Matrix = vector< vector< T > >; // https://ei1333.github.io/algorithm/union-find.html struct UnionFind { vector< int > data; UnionFind(int sz) { data.assign(sz, -1); } bool unite(int x, int y) { x = find(x), y = find(y); if(x == y) return(false); if(data[x] > data[y]) swap(x, y); data[x] += data[y]; data[y] = x; return(true); } int find(int k) { if(data[k] < 0) return(k); return(data[k] = find(data[k])); } int size(int k) { return(-data[find(k)]); } }; // https://ei1333.github.io/algorithm/skew-heap.html template< typename T, typename E = T > struct SkewHeap { using G = function< T(T, E) >; using H = function< E(E, E) >; struct Node { T key; E lazy; Node *l, *r; }; const bool rev; const G g; const H h; SkewHeap(bool rev = false) : g([](const T &a, const E &b) { return a + b; }), h([](const E &a, const E &b) { return a + b; }), rev(rev) {} SkewHeap(const G &g, const H &h, bool rev = false) : g(g), h(h), rev(rev) {} Node *propagate(Node *t) { if(t->lazy != 0) { if(t->l) t->l->lazy = h(t->l->lazy, t->lazy); if(t->r) t->r->lazy = h(t->r->lazy, t->lazy); t->key = g(t->key, t->lazy); t->lazy = 0; } return t; } Node *merge(Node *x, Node *y) { if(!x || !y) return x ? x : y; propagate(x), propagate(y); if((x->key > y->key) ^ rev) swap(x, y); x->r = merge(y, x->r); swap(x->l, x->r); return x; } void push(Node *&root, const T &key) { root = merge(root, new Node({key, 0, nullptr, nullptr})); } T top(Node *root) { return propagate(root)->key; } void pop(Node *&root) { propagate(root); auto *temp = root; root = merge(root->l, root->r); delete temp; } bool empty(Node *root) const { return !root; } void add(Node *root, const E &lazy) { if(root) { root->lazy = h(root->lazy, lazy); propagate(root); } } Node *makeheap() { return nullptr; } }; // https://ei1333.github.io/algorithm/chu-liu-edmond.html template< typename T > struct MinimumSpanningTreeArborescence { using Pi = pair< T, int >; using Heap = SkewHeap< Pi, int >; using Node = typename Heap::Node; const Edges< T > &es; const int V; T INF; MinimumSpanningTreeArborescence(const Edges< T > &es, int V) : INF(numeric_limits< T >::max()), es(es), V(V) {} T build(int start) { auto g = [](const Pi &a, const T &b) { return Pi(a.first + b, a.second); }; auto h = [](const T &a, const T &b) { return a + b; }; Heap heap(g, h); vector< Node * > heaps(V, heap.makeheap()); for(auto &e : es) heap.push(heaps[e.to], {e.cost, e.src}); UnionFind uf(V); vector< int > used(V, -1); used[start] = start; T ret = 0; for(int s = 0; s < V; s++) { stack< int > path; for(int u = s; used[u] < 0;) { path.push(u); used[u] = s; if(heap.empty(heaps[u])) return -1; auto p = heap.top(heaps[u]); ret += p.first; heap.add(heaps[u], -p.first); heap.pop(heaps[u]); int v = uf.find(p.second); if(used[v] == s) { int w; Node *nextheap = heap.makeheap(); do { w = path.top(); path.pop(); nextheap = heap.merge(nextheap, heaps[w]); } while(uf.unite(v, w)); heaps[uf.find(v)] = nextheap; used[uf.find(v)] = -1; } u = uf.find(v); } } return ret; } }; void solve() { int n, m; cin >> n >> m; vector a(n); rep(i,0,n) cin >> a[i]; Edges es; rep(i,0,m) { int u, v; cin >> u >> v; --u, --v; es.eb(u, v, -a[u]), es.eb(v, u, -a[v]); } rep(i,0,n) { es.eb(n, i, 0); } MinimumSpanningTreeArborescence msta(es, n+1); cout << -msta.build(n) << endl; } int main() { int t; cin >> t; while(t--) solve(); return 0; }