并查集学习整理(二)
在做了畅通工程这道题后我又碰到了另外一个修路的题修复公路
内容
某地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车,政府派若干个工程队同时修复这些公路。给出该地区的村庄数 NNN,和公路数 MMM,公路是双向的。并告诉你每条公路的连着哪两个村庄,什么时候能修完这条公路,问最早什么时候任意两个村庄能够通车。
输入格式
第一行两个正整数 N,M (2≤N≤100,1≤M≤105),分别表示村庄的个数和公路数。下面 M行,每行三个正整数 x,y,t(1≤x,y≤n,1≤t≤105),告诉你这条公路连着 x,y两个村庄,在时间 t 时能修复完成这条公路。
输出格式
如果全部公路修复完毕仍然存在两个村庄无法通车,则输出 −1,否则输出最早什么时候任意两个村庄能够通车。
样例输入
4 4
1 2 6
1 3 4
1 4 5
4 2 3
样例输出
5
解题思路
其实这道题是比较水的题,基本还是并查集模板的应用,只是有所修改。拿到题,读完之后发现要找畅通的最小时间,显然输入的顺序是随机的,所以我们就需要对输入的数据进行排序,但是每次输入的数据有三个,所以要用结构体进行存储,然后对结构体进行排序(话说之前根本不知道结构体里面也可以排序,这次学到了),排序完成之后,就是对输入的村庄找修好的路了,也就是找父对象,用并查集可以做到。但是要注意,题中让我们找到任意两个村庄畅通的最短时间,我们发现,要想满足,只需要修n-1条路就行,我们让t=n,每修好一条路让t-1,当t=1的时候刚好满足题意,这个时候输出修路用的时间就可以啦。当然如果遍历完仍然没有畅通输出-1就行,也就是后面else
输出就行。
附上AC代码
#include<bits/stdc++.h>
using namespace std;
int pre[1005];
int s[1005],t;
//并查集模板
int find(int x)
{
if(pre[x]==x)
return x;
else
return find(pre[x]);
}
void fff(int x,int y)
{
int fx,fy;
fx=find(x);
fy=find(y);
if(fx!=fy)
{
t--;//修好一条路t--
pre[fx]=fy;
}
}
//将输入的数据存到结构体中方便使用
struct road
{
int a;
int b;
int c;
}k[100005];
bool cmp(const road x,const road y)
{
return x.c<y.c;
}
//const定义的是常量(注意此处结构体排序函数的写法ps:这里是根据k[i].c进行排序)
int main()
{
int n,m;
cin>>n;
t=n;//总共有n个村庄要修路
int i,j;
for(i=1;i<=n;i++)
{
pre[i]=i;
}//并查集
cin>>m;
for(i=1;i<=m;i++)
{
cin>>k[i].a>>k[i].b>>k[i].c;
}//输入数据存到结构体
sort(k+1,k+m+1,cmp);//排序
int time;
for(int i=1;i<=m;i++)
{
fff(k[i].a,k[i].b);
if(t==1)
{
time=k[i].c;
break;
}
}
if(t==1)
{
cout<<time;
}
else
cout<<"-1";
return 0;
}
学完入门的只是一些简单的题很容易就能做出了,但是有一些题就不行了,它就涉及到了并查集的进阶,下次我们再总结,嘿嘿…