最小生成树,不过有些边是已经有的,有些边是没有的。这里有两种算法,一种是如下采用并查集的方式,另一种是将已经有的边的权值置为0,这样再用Prim或者Kruskal算最小生成树的时候就一定会将这条边选入。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef struct Edge {
int u, v;
int w;
int flag;
}Edge;
Edge e[10005];
int p[105];
bool cmp(Edge a, Edge b) {
return a.w < b.w;
}
void init(int n) {
for(int i = 1; i <= n; i++) {
p[i] = i;
}
}
int find(int x) {
return p[x] == x ? x : (p[x] = find(p[x]));
}
int main() {
int n, m;
while(scanf("%d", &n), n != 0) {
int ans;
m = n*(n-1)/2;
for(int i = 0; i < m; i++) {
scanf("%d%d%d%d", &e[i].u, &e[i].v, &e[i].w, &e[i].flag);
}
sort(e, e+m, cmp);
init(n);
for(int i = 0; i < m; i++) {
if(1 == e[i].flag) {
int t1 = find(e[i].u);
int t2 = find(e[i].v);
if(t1 != t2) {
p[t1] = t2;
}
}
}
ans = 0;
for(int i = 0; i < m; i++) {
if(0 == e[i].flag) {
int t1 = find(e[i].u);
int t2 = find(e[i].v);
if(t1 != t2) {
p[t1] = t2;
ans += e[i].w;
}
}
}
printf("%d\n", ans);
}
return 0;
}