#include<iostream>
#include<algorithm>
using namespace std;
//int edge[110][110];
int flag[110];
int p[110];
struct node
{
    int start;
    int end;
    int cost;
};
node edge[10010];
int cmp(const node& c,const node& d)
{
    return c.cost<d.cost;
}
int FindSet(int x)
{
    int temp=p[x];
    if(x!=p[x])
        p[x]=FindSet(temp);
    return p[x];
}
void Union(int x,int y)
{
    int A=FindSet(x);
    int B=FindSet(y);
    if(A==B)
        return;
    if(A<B)
        p[B]=A;
    else
        p[A]=B;
}
int main()
{
    memset(edge,0,110*sizeof(edge[0]));
    memset(flag,0,110*sizeof(flag[0]));
    int N,Q,start,end,j;
    int sum=0;
    cin>>N;
    for(int i=0;i<N;i++)
        p[i]=i;
    int k=0;
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
    {
        edge[k].start=i;
        edge[k].end=j;
        cin>>edge[k].cost;
        k++;
    }
    cin>>Q;
    for(int i=0;i<Q;i++)
    {
        cin>>start>>end;
        //flag[start-1]=flag[end-1]=true;
        Union(start-1,end-1);
    }
    sort(edge,edge+N*N,cmp);
    //for(int i=N;i<N*N;i++)
    //    cout<<edge[i].cost<<" ";
    
    for(int i=N;i<N*N;i++)
        {
            //if(!flag[edge[i].start]||!flag[edge[i].end])
            if(FindSet(edge[i].start)!=FindSet(edge[i].end))
            {
                
                sum+=edge[i].cost;
                Union(edge[i].start,edge[i].end);
                flag[edge[i].start]=flag[edge[i].end]=true;
            }
        }
    cout<<sum<<endl;
    return 0;
}