/*
* Manshui's MST Kruskal, Linked List Implementation
*
* Preprocessing:
* Merge corresponding sets based on existing edges .. Then Kruskal
*
* Another method:
* Change the weight of an existing edge to 0.
*
*/
# Include <cstdio>
# Include <algorithm>
Using namespace STD;
Const int maxn = 100 + 5;
Int N, totedgenum, G [maxn] [maxn], Q, ans;
Struct sedge {
Int W, U, V;
};
Sedge edge [maxn * maxn];
Struct snode {
Int num, Len;
Snode * rep, * next;
};
Snode * head [maxn], * tail [maxn], * node [maxn];
Snode * makeset (snode * X ){
Head [X-> num] = x; tail [X-> num] = X;
X-> rep = x; X-> next = NULL;
X-> Len = 1;
Return X;
}
Snode * findset (snode * X ){
Return X-> rep;
}
Snode * unionset (snode * LHS, snode * RHs ){
Snode * First, * Second, * cur;
If (LHS-> rep-> Len> = RHS-> rep-> Len ){
First = LHS-> rep; second = RHS-> rep;
}
Else {
First = RHS-> rep; second = LHS-> rep;
}
Cur = second;
While (cur! = NULL ){
Cur-> rep = first;
Cur = cur-> next;
}
Tail [first-> num]-> next = head [second-> num];
Tail [first-> num] = tail [second-> num];
Head [second-> num] = head [first-> num];
Return first;
}
Int CMP (const void * LHS, const void * RHs ){
Sedge * A = (sedge *) LHS; sedge * B = (sedge *) RHS;
Return a-> W-B-> W;
}
Void mstkruskal (){
Qsort (edge, totedgenum, sizeof (sedge), CMP );
/*
For (INT I = 0; I <totedgenum; I ++ ){
Printf ("% d", edge [I]. W );
}
Printf ("\ n ");
*/
For (INT I = 0; I <totedgenum; I ++ ){
If (findset (node [edge [I]. u])! = Findset (node [edge [I]. V]) {
Ans + = edge [I]. W;
Unionset (node [edge [I]. u], node [edge [I]. V]);
}
}
}
Int main (){
// Graph input
Scanf ("% d", & N );
For (INT I = 0; I <n; I ++ ){
For (Int J = 0; j <n; j ++ ){
Scanf ("% d", & G [I] [J]);
}
}
Totedgenum = 0;
For (INT I = 0; I <n; I ++ ){
For (Int J = 0; j <= I; j ++ ){
Edge [totedgenum]. U = I;
Edge [totedgenum]. V = J;
Edge [totedgenum]. W = G [I] [J];
Totedgenum ++;
}
}
// Initialization
For (INT I = 0; I <n; I ++ ){
Node [I] = new snode;
Node [I]-> num = I;
Makeset (node [I]);
}
Scanf ("% d", & Q );
Int U, V;
For (INT I = 0; I <q; I ++ ){
Scanf ("% d", & U, & V );
If (node [U-1]-> rep! = Node [V-1]-> REP)
Unionset (node [U-1], node [V-1]);
}
// Kruskal
Mstkruskal ();
Printf ("% d \ n", ANS );
Return 0;
}