//最小生成树 //只需将已经建成的路的边权值置零即可 //然后对边进行排序,建立并查集,用Kruscal #include<iostream> #include<algorithm> #include<vector> #define MAX 105 using namespace std; int N,Q; int G[MAX][MAX]; int fa[MAX]; struct Edge { int u,v,w; Edge(int uu,int vv,int ww) { u = uu; v = vv; w = ww; } }; vector<Edge> E; void readGraph() { int u,v; scanf("%d",&N); for(int i = 1;i <= N;++i) for(int j = 1;j <= N;++j) scanf("%d",&G[i][j]); scanf("%d",&Q); while(Q--) { scanf("%d%d",&u,&v); G[u][v] = G[v][u] = 0; } } void readEdge() { for(int i = 1;i <= N;++i) for(int j = 1;j <= N;++j) { if(j == i) continue; E.push_back(Edge(i,j,G[i][j])); } } bool cmp(Edge a,Edge b) { return a.w < b.w; } void initSet()//建立并查集 { for(int i = 1;i <= N;++i) fa[i] = i; } int Find(int x) { if(x == fa[x]) return x; else return fa[x] = Find(fa[x]);//路径压缩 } bool Union(int x,int y) { x = Find(x); y = Find(y); if(x == y) return 0; else { fa[x] = y; return 1; } } int Kruscal() { initSet(); int u,v,w,ans = 0; sort(E.begin(),E.end(),cmp); for(int i = 0;i < E.size();++i) { u = E[i].u; v = E[i].v; w = E[i].w; if(Union(u,v)) ans += w; } return ans; } int main() { readGraph(); readEdge(); printf("%d/n",Kruscal()); return 0; }