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 }