。由于已经建好的路不一定是在最小生成树中,所以这个边数的约束没有必要,只要连通的条件达成就行。
#include <bits/stdc++.h> using namespace std; //定义的边 struct Edge { int a; int b; int weight; // int isBuilt; Edge(int _a, int _b, int _weight, int _isBuilt) { a = _a; b = _b; // isBuilt = _isBuilt; if (_isBuilt == 1) {//如果已经建好了,这条路的权重就是零。只要加入并查集就好 weight = 0; } else { weight = _weight; } } }; int father[1010]; //初始化 void InitDisjointSet(int n) { //0~n-1 for (int i = 0; i < n; ++i) { father[i] = i; } } //找爸爸 int FindDisjointset(int u) { if (u == father[u]) { return u; } else { father[u] = FindDisjointset(father[u]); return father[u]; } } //合并 void UnionDisjointSet(int u, int v) { int uroot = FindDisjointset(u); int vroot = FindDisjointset(v); father[vroot] = uroot; } //将边按权值从小到大排列 bool compare(Edge lhs, Edge rhs) { /* sort是基于快速排序实现的,基于比较的排序。默认<。 * 重点编程:设计“compare”函数。返回值:bool;函数名:无所谓;两个参数:类型和容器元素一致。 * 当左边和右边不会发生交换时,返回真;发生交换时,返回假。*/ return lhs.weight < rhs.weight; } //Kruskal int Kruskal(int N, vector<Edge> &roads) { int roadCount = 0; int weighSum = 0; sort(roads.begin(), roads.end(), compare); for (int i = 0; i < roads.size() ; ++i) { int a = roads[i].a; int b = roads[i].b; int weight = roads[i].weight; if (FindDisjointset(a) != FindDisjointset(b)) { UnionDisjointSet(a, b); weighSum += weight; roadCount++; // 由于已经建好的路不一定是在最小生成树中,所以这个边数的约束没有必要,只要上述连通的条件达成就行。 // if (roadCount == N - 1) {//达到最大边数 // break; // } } } return weighSum; } int main() { int N; while (scanf("%d", &N) != EOF) { if (0 == N) { return 0; } //初始化 vector<Edge> roads; InitDisjointSet(N + 1); int edgeNum = N * (N - 1) / 2; //录入信息 for (int i = 0; i < edgeNum; ++i) { int a; int b; int weight; int isBuilt; scanf("%d%d%d%d", &a, &b, &weight, &isBuilt); Edge r(a, b, weight, isBuilt); roads.push_back(r); } printf("%d\n", Kruskal(N, roads)); roads.clear(); } return 0; }