题目背景
A 地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。
题目描述
给出 A 地区的村庄数 N,和公路数 M,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。
问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)。
输入格式
第 1 行两个正整数 N,M。
下面 M 行,每行 3 个正整数 x,y,t,告诉你这条公路连着 x,y 两个村庄,在时间t时能修复完成这条公路。
输出格式
如果全部公路修复完毕仍然存在两个村庄无法通车,则输出 -1,否则输出最早什么时候任意两个村庄能够通车。
样例
样例输入 #1
4 4
1 2 6
1 3 4
1 4 5
4 2 3
样例输出 #1
5
提示
1 ≤ x, y ≤ N ≤ 10 ^ 3,1 ≤ M, t ≤ 10 ^ 5。
村庄用公路相连,判断两村庄能否通车,这可以想到用并查集,如果两个村庄已经用公路相连了,那么这两个村庄就是并在一起的。首先我们要了解并查集的定义,它是一种十分精巧且实用的树形数据结构,它主要处理一些不相交集合的合并与查询问题。
初始化数组:
for(int i=1; i<=N; i++) {
b[i] = i;
}
查询:
int find(int k)
{
if(b[k] == k){
return k;
}
return b[k] = find(b[k]);
}
合并:
int x = find(a[i].x);
int y = find(a[i].y);
if(x != y) {
b[x] = y;
}
这就是简单并查集里的查询好合并的操作,当我们了解好这些操作后,题目还要考虑最早什么时候任意两个村庄能够通车。所以我们要进行排序,把时间最短的排在最前面。这里要考虑村庄,公路和时间,所以我们要使用结构体来定义变量。
struct structs{
int x;
int y;
int t;
};
int main()
{
int N,M;
scanf("%d %d",&N,&M);
struct structs a[MAX];
for(int i=1; i<=M; i++) {
scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].t);
}
}
再进行排序,把时间最短的排在最前面,因为要考虑代码运行的时间,所以我们不使用冒泡排序和选择排序,如果用它们时间会超限,所以我们使用最快的快排;
int partition(struct structs a[], int low, int high) {
struct structs pivot = a[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++) {
if (a[j].t < pivot.t) {
i++;
struct structs temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
struct structs temp = a[i + 1];
a[i + 1] = a[high];
a[high] = temp;
return (i + 1);
}
void quickSort(struct structs a[], int low, int high) {
if (low < high) {
int pivot = partition(a, low, high);
quickSort(a, low, pivot - 1);
quickSort(a, pivot + 1, high);
}
}
排序好之后我们就进行合并的操作,当合并一次就令村庄数减一,当村庄只剩一个时,就是最早的时间可以通车,不然的话就没有最早的时间可以通车;可以想象两个村庄合并成一个村庄,最终只剩一个村庄时,肯定都合并完了,当然是最早的时间通车;
for(int i=1; i<=M; i++) {
int x = find(a[i].x);
int y = find(a[i].y);
if(x != y) {
b[x] = y;
N--;
}
if(N == 1) {
printf("%d",a[i].t);
return 0;
}
}
printf("-1");
完整代码如下:
#include <stdio.h>
#define MAX 100005
int b[MAX];
struct structs{
int x;
int y;
int t;
};
int partition(struct structs a[], int low, int high) {
struct structs pivot = a[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++) {
if (a[j].t < pivot.t) {
i++;
struct structs temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
struct structs temp = a[i + 1];
a[i + 1] = a[high];
a[high] = temp;
return (i + 1);
}
void quickSort(struct structs a[], int low, int high) {
if (low < high) {
int pivot = partition(a, low, high);
quickSort(a, low, pivot - 1);
quickSort(a, pivot + 1, high);
}
}
int find(int k)
{
if(b[k] == k){
return k;
}
return b[k] = find(b[k]);
}
int main()
{
int N,M;
scanf("%d %d",&N,&M);
struct structs a[MAX];
for(int i=1; i<=M; i++) {
scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].t);
}
quickSort(a, 1, M); // 注意这里的边界
for(int i=1; i<=N; i++) {
b[i] = i;
}
for(int i=1; i<=M; i++) {
int x = find(a[i].x);
int y = find(a[i].y);
if(x != y) {
b[x] = y;
N--;
}
if(N == 1) {
printf("%d",a[i].t);
return 0;
}
}
printf("-1");
return 0;
}