并查集是一个什么样的东西呢,就是一个祖宗带着一堆孙子的问题,而若对应到图上,我们可以看到这样可以视为一个连通块的问题。
并查集有几个模板,几个基本操作。
我们可以合并集合,查询集合。
我们可以在基础并查集上加上一个维护其长度的代码,也可以做到一个使得并查集的距离被保存。
在这里不再详述。
回到题目。
给出 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;
}