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