1 //克鲁斯卡尔(最小生成树)
2 #include<cstdio>
3 #include<iostream>
4 #include<algorithm>
5 using namespace std;
6
7 const int maxn = 100005;
8 int n, t;
9 struct node
10 {
11 int bagin, end, len;
12 }arr[maxn];
13 int fa[maxn];
14
15 void init()
16 {
17 for (int i = 0; i <= n; i++)
18 {
19 fa[i] = i;
20 }
21 }
22
23 bool cmp(node a, node b)
24 {
25 return a.len<b.len;
26 }
27
28 int find(int x)
29 {
30 if (x != fa[x])
31 fa[x] = find(fa[x]);
32 return fa[x];
33 }
34
35 int main()
36 {
37 while (cin >> n)
38 {
39 t = 0;
40 for (int i = 1; i <= n; i++)
41 {
42 for (int j = 1; j <= n; j++)
43 {
44 int x;
45 cin >> x;
46 arr[t].bagin = i; arr[t].end = j; arr[t].len = x;
47 t++;
48 }
49 }
50 sort(arr, arr + t, cmp);
51 init();
52 int m;
53 cin >> m;
54 while (m--)
55 {
56 int a, b;
57 cin >> a >> b;
58 int fx, fy;
59 fx = find(a); fy = find(b);
60 fa[fy] = fx;
61 }
62 int ans = 0;
63 for (int i = 0; i<t; i++)
64 {
65 int fx, fy;
66 fx = find(arr[i].bagin);
67 fy = find(arr[i].end);
68 if (fx != fy)
69 {
70 ans += arr[i].len;
71 fa[fy] = fx;
72 }
73 }
74 cout << ans << endl;
75 }
76 return 0;
77 }