修复公路——C语言(并查集、排序)

题目背景
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;
}

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值