本题关键在于如何实现克鲁斯卡尔算法。该算法需要将边从小到大进行排序,每次选出不会成环且最小的边,直到边数为节点数减去1,意味着最小生成树生成完成
/*请计算最小的公路总长度。输入描述:测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离, 每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。当N为0时,输入结束,该用例不被处理。 输出描述:对每个测试用例,在1行里输出最小的公路总长度。 输入: 3 1 2 1 1 3 2 2 3 4 4 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5 0 输出: 3 5 */ #include <bits/stdc++.h> using namespace std; int father[1010]; void initialize(int n) { for (int i = 0; i < n; i++) { father[i] = i; } } int findset(int n) { if (n == father[n]) { return n; } else { father[n] = findset(father[n]); return father[n]; } } void unionset(int u, int v) { int uroot = findset(u); int vroot = findset(v); father[vroot] = uroot; } struct Edge { int u, v; int weight; Edge(int _u, int _v, int _weight) { u = _u; v = _v; weight = _weight; } }; bool compare(Edge lhs,Edge rhs){ return lhs.weight<rhs.weight; } int main() { int n,u,v,weight; while (scanf("%d",&n)!=EOF) { if (n == 0) { break; } vector<Edge> vec; initialize(n+1); for (int i = 0; i < n*(n-1)/2; i++) { scanf("%d%d%d",&u,&v,&weight); Edge e(u,v,weight); vec.push_back(e); //读取并压入边表型动态数组 } //实现克鲁斯卡尔算法 sort(vec.begin(),vec.end(), compare);//将各个序列进行升序排序 int totalweight = 0; int curEdgeNum = 0; for(int i=0;i<vec.size();i++){ int u=vec[i].u; int v=vec[i].v; int weight=vec[i].weight; if(findset(u)!=findset(v)){ unionset(u,v); ++curEdgeNum; totalweight+=weight; if(curEdgeNum==n-1){ break; } } } printf("%d\n",totalweight); } return 0; }