#include using namespace std; const int N = 310; int n; int g[N][N]; int dis[N]; bool st[N]; int res; // 最小生成树里面边的长度之和 void prim() { memset(dis, 0x3f, sizeof dis); // 初始化所有距离为INF dis[0] = 0; // 超级源点是在生成树中的 for (int i = 0; i <= n; i++) { // 注意:这里因为引入了超级源点,所以点的个数是n+1 int t = -1; for (int j = 0; j <= n; j++) if (!st[j] && (t == -1 || dis[t] > dis[j])) t = j; if (i) res += dis[t]; // 有超级源点的题,是必然存在最小生成树的 // 注意这里也是需要从0~n共n+1个 for (int j = 0; j <= n; j++) if (!st[j] && dis[j] > g[t][j]) dis[j] = g[t][j]; st[t] = true; } } int main() { cin >> n; // 建立超级源点(0 <-> 1~n ),点权转化为超级源点到此节点的边权 for (int i = 1; i <= n; i++) { int c; cin >> c; g[i][0] = g[0][i] = c; } // 本题是按矩阵读入的,不是按a,b,c方式读入的 for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) cin >> g[i][j]; // 利用prim计算最小生成树 prim(); cout << res << endl; return 0; }