并查集学习整理(二)

并查集学习整理(二)

在做了畅通工程这道题后我又碰到了另外一个修路的题修复公路

内容

某地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车,政府派若干个工程队同时修复这些公路。给出该地区的村庄数 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;
 }

学完入门的只是一些简单的题很容易就能做出了,但是有一些题就不行了,它就涉及到了并查集的进阶,下次我们再总结,嘿嘿…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值