#include<cstdio>
#include<iostream>
#include<string.h>
#include<cmath>
#define maxn 105
#define inf 9999999
int vis[maxn],n;//用来表示点是否在集合里
int mincost[maxn];//用来记录从集合出来到每个点的最小距离
int mapp[maxn][maxn];
using namespace std;
void init()
{
for(int i=1;i<=n;i++) vis[i]=0;
fill(mincost,mincost+n+1,inf);
}
void prim()
{
mincost[1]=0;
int res=0;
while(1)
{
int v=-1;
for(int i=1;i<=n;i++) if(!vis[i]&&(v==-1||mincost[i]<mincost[v])) v=i;//找出离集合最近的点
if(v==-1) break;
vis[v]=1;
res+=mincost[v];
for(int i=1;i<=n;i++) mincost[i]=min(mincost[i],mapp[v][i]);
}
printf("%d\n",res);
}
int main()
{
while(~scanf("%d",&n))
{
init();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int x;
scanf("%d",&x);
mapp[i][j]=mapp[j][i]=x;
}
}
int q;
scanf("%d",&q);
while(q--)
{
int a,b;
scanf("%d %d",&a,&b);
mapp[a][b]=0;//用来表示集合里面已经存在的
mapp[b][a]=0;
// vis[a]=1;
// vis[b]=1;
// for(int i=1;i<=n;i++) mincost[i]=minn(mincost[i],mapp[a][i]);//更新集合到每个点的最小距离 v为新加路的点
// for(int i=1;i<=n;i++) mincost[i]=minn(mincost[i],mapp[b][i]);
}
prim();
}
return 0;
}