。由于已经建好的路不一定是在最小生成树中,所以这个边数的约束没有必要,只要连通的条件达成就行。
#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;
}

京公网安备 11010502036488号