HDU 1879

最小生成树,不过有些边是已经有的,有些边是没有的。这里有两种算法,一种是如下采用并查集的方式,另一种是将已经有的边的权值置为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;
}


你可能感兴趣的:(HDU 1879)