哟西!又到了晚间写题解的时间啦!!!今天呢,还是和昨天一样是并查集的算法呀!!!但是奥,小小的不一样,因为我们今天的题目还要用到Krukal算法,简单来说就是并查集的升级版题目呀!!!Emmmmm...开始之前,按照惯例,我们来稍(xue)微地讲一下,什么是Kruskal算法。
Krukal算法
克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。与普里姆算法(Prim)不同,它的时间复杂度为O(eloge)(e为网中的边数),所以,适合于求边稀疏的网的最小生成树。克鲁斯卡尔(Kruskal)算法从另一途径求网的最小生成树。其基本思想是:假设连通网G=(V,E),令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),概述图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点分别在T中不同的连通分量上,则将此边加入到T中;否则,舍去此边而选择下一条代价最小的边。依此类推,直至T中所有顶点构成一个连通分量为止
百度的解释就是如上。
简单点来讲就是要把所有的点联通到一起,同时求出最小的权值/大概是这样的一个意思吧...如果有什么问题的话还请各位在评论区指正。
大概的解释就是这样。至于并查集的话,就是合并+查找。Okay,知道了这两个基本的算法,我们就来解决一下今天的题目吧。其实这个是我昨天晚上写的,不过太晚了,没时间更新题解,所以就放到了今天。哦对了,并查集+Kruskal就变成了一个新的知识点,叫做最小生成树。/*快快快,这是重点哦,下次考试必考的!敲黑板.jpg*/
好啦,接下来,我们来看下题目。
A地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。
题目描述
给出A地区的村庄数N,和公路数M,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)
输入输出格式
输入格式:
第1行两个正整数N,M
下面M行,每行3个正整数x, y, t,告诉你这条公路连着x,y两个村庄,在时间t时能修复完成这条公路。
输出格式:
如果全部公路修复完毕仍然存在两个村庄无法通车,则输出-1,否则输出最早什么时候任意两个村庄能够通车。
输入输出样例
输入样例:
4 4
1 2 6
1 3 4
1 4 5
4 2 3
输出样例:
5
说明
N<=1000,M<=100000
x<=N,y<=N,t<=100000
这就是题目了,乍一看是不是用我们的并查集板子就可以解决呢!!! 嘿嘿嘿,这可是最小生成树欸!如果只用一个并查集的板子,那肯定是解决不了问题的。因为他问到了一个最少,也就是说要出现比较,我们要找到最早的那个时间!让所有的村庄之前都产生联系!!!
那么这样的话,思路就出来啦!并查集+排序。按照题目的意思,他每一行会给我们三个数字,而这个排序不能只排其中的一个,而是要带着所有的数据一起排序,打包并进行排序。那是什么呢,就是结构体排序!不会结构体排序的小伙伴看这里哦!
struct road{
int x,y,t;
}a[N];//首先我们要定义一个结构体,因为有三个数字所有我们的结构体里面应该是三个变量
bool cmp(road b,road c) {
return b.t <c.t;
}//排序的话用这个函数进行比较,bool的话主要是简便,如果不想用bool类型的函数的话,
//使用int类型的函数也是可以的。
sort(a+1,a+m+1,cmp);
//在使用sort排序的时候不要忘记加头文件算法哦
对!就是这样的!排序加上并查集就可以解决这个问题啦!
欸嘿,最后啊,其实我还有个小小的问题留给大家思考,就是排序后的那个if条件是为什么。明白的小伙伴在评论区留言吧!!!好了,我要继续打游戏学习去了!
#include<bits/stdc++.h>
#define N 110000
using namespace std;
int parent[N],n,m;
struct road{
int x,y,t;
}a[N];
bool cmp(road b,road c) {
return b.t <c.t;
}
void init()
{
for(int i=1;i<=n;i++)
{
parent[i]=i;
}
}
int find(int x)
{
if(parent[x]==x)
{
return x;
}else {
parent[x]=find(parent[x]);
return parent[x];
}
}
void uni(int x,int y)
{
int dx=find(x);
int dy=find(y);
if(dx!=dy)
{
parent[dy]=dx;
n--;
}
}
int main()
{
scanf("%d %d",&n,&m);
init();
for(int i=1;i<=m;i++){
scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].t);
}sort(a + 1, a + 1 + m, cmp);
for(int i=1;i<=m;i++){
uni(a[i].x,a[i].y);
if(n==1){
printf("%d\n",a[i].t);
return 0;
}
}printf("-1\n");
return 0;
}