#include#include #include #include using namespace std; struct edge{ int begin; int end; int weight; }; const int maxn = 110; int father[maxn]; edge e[maxn*maxn]; int map[maxn][maxn]; int find(int x){ if( x == father[x]){ return x; } father[x] = find(father[x]); return father[x]; } int kruscal(int count){//使用kruscal算法来生成最小生成树并计算带权路径和 int i; int sum = 0;//用sum来记录最小s生成树的边权和 for( i = 1 ; i < maxn ; ++i){ father[i] = i; } for( i = 0 ; i < count ; ++i){//枚举有序边集中的每一条边 int fx = find(e[i].begin); int fy = find(e[i].end); if(fx != fy){//若第k条边的两个端点i,j 分别属于两颗不同的子树 father[fx] = fy;//则将节点i所在的子树并入节点j所在的子树中 sum += e[i].weight; } } return sum; } bool compare(const edge& a , const edge& b){ return a.weight < b.weight; } //以上是用kruscal算法来解决问题的基本模板..... int main(){ int n; while(scanf("%d",&n)!=EOF){ int i,j; for(i = 1 ; i <= n ; ++i){ for(j = 1 ; j <= n ; ++j){ scanf("%d",&map[i][j]); } } int count = 0; for(i = 1 ; i <= n ; ++i){ for(j = i+1 ; j <= n ; ++j){ e[count].begin = i; e[count].end = j; e[count++].weight = map[i][j]; } } sort(e,e+count,compare);//kruscal算法要求边有序 int sum = kruscal(count); printf("%d\n",sum); } return 0; }