Description
Input
Output
Sample Input
4 0 4 9 21 4 0 8 17 9 8 0 16 21 17 16 0
Sample Output
28
用Kruscal算法最小生成树时注意一条边一条边输入,不用的边别输入;
事先要对每个顶点的父亲情况初始化一下,即p[i] = i ;
基本思想是先把所有边按长短排序,小的在前,再每条边的两个顶点依次遍历,如果祖先不同则把边的权值加进去,再合并,即前者祖先为后者祖先。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; int n; int cnt; int p[110]; int ans; struct edge{ int u; int v; int w; int p; }e[10010]; int find(int x){ return p[x] == x ? x : p[x] = find(p[x]); } int cmp(edge a , edge b){ return a.w < b.w; } int Kruskal(){ ans = 0; int i; for(i = 0; i < n; i ++) p[i] = i; sort(e + 1, e + cnt + 1, cmp); for(i = 1; i <= cnt; i ++){ int x = find(e[i].u); int y = find(e[i].v); if(x != y){ ans += e[i].w; p[x] = y; } } } int main(){ int i, j, aa; while(~scanf("%d", &n)){ cnt = 0; for(i = 0; i < n; i ++){ for(j = 0; j < n; j ++){ if(j <= i) scanf("%d", &aa); else{ scanf("%d", &e[++cnt].w); e[cnt].u = i; e[cnt].v = j; } } } for(i = 0; i < n; i ++) p[i] = i; Kruskal(); cout << ans << endl; } return 0; }