【洛谷】P1111 修复公路(学习记录)
今天主要是解决题目。重点的问题就是修复公路,将里面要用到的关键代码部分和思路总结一下。
题目如下:
这道题的整体思路是利用并查集。我一开始写题时审题有问题,以为要用到并查集和动态规划,后面看题解发现了正确的思路。
这道题,注意一个地方,t 的含义是什么?是指在 t 时能够修复完某条公路,而不是指修复某条公路需要花 t 个小时。
那么基于这点,得到一个求得最早修好一条连接所有村庄的公路的方法---->按照每条公路要修完要到 t 时的时间大小排序,升序排列。(排列的是结构体,为了方便操作,创建一个结构体)
以下是结构体组成:
struct new {
int x;
int y;
int t;
}load[100001];
然后是一个升序排列结构体,用到了qsort函数
(这个函数我还没学透,指个路复习:【C语言】qsort()函数详解:能给万物排序的神奇函数-CSDN博客)
下面是排列结构体的代码:
int compe(const void* e, const void* f) {
struct new* road1 = (struct new*)e;
struct new* road2 = (struct new*)f;
return road1->t - road2->t;
}
//这里要注意,比较方法是要自己写的,qsort会按你比较后返回的值进行排序处理
qsort(load+1, M, sizeof(struct new), compe);
然后我们按顺序修路就好,将路的根节点都指向同一个就代表修好了,每次修完一条路都要判断是否已经成功修完一条连接所有村庄的路了。
修路就用了经典的并查集,利用一个combine函数让根节点一致,find函数查找根节点。
判断部分用了一个test函数,这里我目前知道有两种判断方法。
一种是找一个路的根节点为样例,for循环一下看看是不是所有根节点都和样例一样,如果有不同,就代表还没全部连通。
第二种是,将pre[ ]传入test函数,如果有pre[ i ] = i的情况就代表找到了一个根节点,记录一下,num++,但是num一旦大于1,那就说明根节点不止一个了,那就说明路还没通全部村庄。
(代码中也有比较详细的注释,记录一下,方便复习理解)
以下是ac代码:
#include<stdio.h>
#include<stdlib.h>
int pre[1001];
int num = 0;
int N = 0;
int M = 0;
struct new {
int x;
int y;
int t;
}load[100001];
//下面两个函数是基本的并查集模型
int find(int a) {
if (pre[a] == a) {
return a;
}
return pre[a] = find(pre[a]);
}
void combine(int x, int y) {
int fx = find(x);
int fy = find(y);
if (fx != fy) {
pre[fx] = y;
}
}
//检查是否每个村庄都已经连通
//这里其实有两种方法,第一种如下,判断是否只有一种根节点就是自己本身的情况。
// 第二种是举例一个根节点,看其他的pre[i]的根节点是不是都与其一致,有不一致的就代表还没连通
int test(int pre[]) {
int num = 0;
for (int i = 1; i <= N; i++) {
//代表只有一个根节点
if (pre[i] == i) {
num++;
}
if (num == 2) {
return 0;
}
}
return 1;
}
//比较结构体(要学会使用qsort函数,各种数据类型的比较函数怎么写要清楚)
int compe(const void* e, const void* f) {
struct new* road1 = (struct new*)e;
struct new* road2 = (struct new*)f;
return road1->t - road2->t;
}
int main() {
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++) {
pre[i] = i;
}
for (int i = 1; i <= M; i++) {
scanf("%d%d%d", &load[i].x, &load[i].y, &load[i].t);
}
qsort(load+1, M, sizeof(struct new), compe);
for (int i = 1; i <= M; i++) {
//只有当路的两端都指向同一个村庄,才代表通路
combine(load[i].x, load[i].y);
if (test(pre)) {
printf("%d", load[i].t);
return 0;
}
}
printf("-1");
return 0;
}