PIPIOJ 1004

代码如有不懂的请在评论区评论,看到尽量解答

CV AC 之后麻烦点个,谢谢!

#include <bits/stdc++.h>

using namespace std;

struct Tub {
	int s, e, c;
};

void init_set(int S[], int size) {
	fill(S, S+size, -1);
} 

int find_set(int S[], int x) {
	while (S[x] > 0) {
		x = S[x];
	}
	
	return x;
}

void union_set(int S[], int r1, int r2) {
	if (r1 == r2) return;
	
	S[r2] = r1;
}

int cmp(const void *a1, const void *a2) {
	struct Tub *b1 = (struct Tub*)a1;
	struct Tub *b2 = (struct Tub*)a2;
	
	if (b1->c > b2->c) return 1;
	if (b1->c < b2->c) return -1;
	return 0;
}

int main() {
	int m, n;
	
	while (scanf("%d %d", &m, &n) != EOF) {
		int cost = 0;
		struct Tub *tub = new struct Tub[n];
		int *set = new int[m+1](); // 并查集,用于判断居民点是否在同一个集合中 
		init_set(set, m+1); // 初始化并查集 
		
		for (int i = 0; i < n; i++) {
			scanf("%d %d %d", &tub[i].s, &tub[i].e, &tub[i].c);
		}
		
		// 克鲁斯卡尔算法 
		// 将输入的管道成本由小到大排序 
		qsort(tub, n, sizeof(struct Tub), cmp);
		
		// 计算连通的最小成本 
		for (int i = 0; i < n; i++) {
			int r1 = find_set(set, tub[i].s);
			int r2 = find_set(set, tub[i].e);
			
			if (r1 != r2) {
				union_set(set, r1, r2);
				cost += tub[i].c;
			}
		}
		
		// 判断所给的 可选管道 是否能够使居民点全部连通
		// 如何判断?
		// 答:判断集合 set 中所有元素是否只有一个根 
		int cnt = 0;
		for (int i = 1; i < m+1; i++) {
			if (set[i] == -1) cnt++;
		} 
		
		if (cnt == 1) {
			printf("%d\n", cost);
		} else {
			printf("?\n");
		}
		
		delete[] tub;
		delete[] set;
	}
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值