//克鲁斯卡尔(最小生成树)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = ;
int n, t;
struct node
{
int bagin, end, len;
}arr[maxn];
int fa[maxn];
void init()
{
for (int i = ; i <= n; i++)
{
fa[i] = i;
}
}
bool cmp(node a, node b)
{
return a.len<b.len;
}
int find(int x)
{
if (x != fa[x])
fa[x] = find(fa[x]);
return fa[x];
}
int main()
{
while (cin >> n)
{
t = ;
for (int i = ; i <= n; i++)
{
for (int j = ; j <= n; j++)
{
int x;
cin >> x;
arr[t].bagin = i; arr[t].end = j; arr[t].len = x;
t++;
}
}
sort(arr, arr + t, cmp);
init();
int m;
cin >> m;
while (m--)
{
int a, b;
cin >> a >> b;
int fx, fy;
fx = find(a); fy = find(b);
fa[fy] = fx;
}
int ans = ;
for (int i = ; i<t; i++)
{
int fx, fy;
fx = find(arr[i].bagin);
fy = find(arr[i].end);
if (fx != fy)
{
ans += arr[i].len;
fa[fy] = fx;
}
}
cout << ans << endl;
}
return ;
}