#include <stdio.h>   // kruskal
#include <algorithm>

using namespace std;

int G[1010][1010], n, m, C;
struct EDGE{
    int w, s, e;
} E[1000001];
bool cmp(EDGE a, EDGE b){ return a.w < b.w; }
int DISJ[1010], ans;

int find(int v)
{
    if( DISJ[v] == v ) return v;
    return find(DISJ[v]);
}

void Union(int a, int b)
{
    int t1 = find(a), t2 = find(b);
    DISJ[t2] = t1;
}

int main()
{
    freopen(".20.in","r",stdin);
    freopen(".20.out","w",stdout);
    scanf("%d", &n);
    for(int i = 0 ; i < n ; i++ ) DISJ[i] = i;
    for(int i = 0 ; i < n ; i++ )
        for(int j = 0 ; j < n ; j++ )
            scanf("%d", &G[i][j]);
    for(int i = 0 ; i < n ; i++ )
        for(int j = i+1 ; j < n ; j++ )
        {
            EDGE t = {G[i][j], i, j};
            E[C++] = t;
        }
    scanf("%d", &m);
    for(int i = 0 ; i < m ; i++ )
    {
        int a, b;
        scanf("%d%d",&a,&b);
        Union(a-1,b-1);
    }
    sort(E,E+C,cmp);
    for(int i = 0 ; i < C ; i++ )
        if( find(E[i].s) != find(E[i].e) )
            Union(E[i].e, E[i].s), ans += E[i].w;
    printf("%d\n", ans);
}
