洛谷1111修复公路(并查集的应用)

本文介绍了如何使用并查集解决洛谷1111题——修复公路问题。并查集用于处理连通块问题,通过合并集合和查询集合等操作。题目要求找出最早能使任意两个村庄通车的时间,通过排序村庄修建时间并利用并查集维护连通状态,可以找到最小时间。文章强调了在C++中使用结构体按时间排序的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

修复公路 - 洛谷

并查集是一个什么样的东西呢,就是一个祖宗带着一堆孙子的问题,而若对应到图上,我们可以看到这样可以视为一个连通块的问题。

并查集有几个模板,几个基本操作。

我们可以合并集合,查询集合。

我们可以在基础并查集上加上一个维护其长度的代码,也可以做到一个使得并查集的距离被保存。

在这里不再详述。

回到题目。

给出 A 地区的村庄数 N,和公路数 M,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)。

N个村庄,要求连通,很明显的并查集问题,但是我们也要考虑到一个关键问题,那就是最小时间。

最小时间应该怎么做到呢?

我们可以对每一个输入的村庄修建的时间进行排序,先将小时间的全部修好,每一次判断一下现在拥有的祖宗节点数,当祖宗节点为一时,这样的连通块就已经变成一个完美的集合,并且我们得到了一个最小的时间。

部分实现的难题。

对于x,y,t三者应该怎么排序呢?

用c++自带的sort自然没有错误,但是我们还不能移动x,y所以,我们可以用结构体来储存,只对时间进行排序。

因此,请铭记这一点,可以用结构体对指定关键字进行排序。

好吧,无话可说了。

代码:

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n, m;
int p[N];

struct node {
	int x;
	int y;
	int t;
} a[100050];

bool cmp(node l, node k) {
	return l.t < k.t;
}

int find(int x) {
	if (p[x] != x)
		p[x] = find(p[x]);
	return p[x];
}

bool check() {
	int sum = 0;
	for (int i = 1; i <= n; i++) {
		if (p[i] == i)
			sum++;
		if (sum == 2)
			return 0;
	}
	return 1;
}

int main() {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		p[i] = i;
	}
	for (int i = 1; i <= m; i++) {
		scanf("%d %d %d", &a[i].x, &a[i].y, &a[i].t);
	}
	sort(a + 1, a + m + 1, cmp);
	for (int i = 1; i <= m; i++) {
		p[find(a[i].x)] = find(a[i].y);
		if (check()) {
			printf("%d\n", a[i].t);
			return 0;
		}
	}
	printf("-1");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值