P1111 修复公路

文章描述了一个关于AA地区地震后公路修复的问题,利用并查集和排序算法来确定最早何时所有村庄能通过修复的公路相通。输入输出示例展示了问题的具体形式,以及代码实现中的关键部分,包括快速排序和并查集的优化,最终实现全部测试用例的正确通过。
摘要由CSDN通过智能技术生成

题目背景

AA地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。

题目描述

给出A地区的村庄数NN,和公路数MM,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)

输入格式

第11行两个正整数N,MN,M

下面MM行,每行33个正整数x, y, tx,y,t,告诉你这条公路连着x,yx,y两个村庄,在时间t时能修复完成这条公路。

输出格式

如果全部公路修复完毕仍然存在两个村庄无法通车,则输出-1−1,否则输出最早什么时候任意两个村庄能够通车。

输入输出样例

输入 #1复制

4 4
1 2 6
1 3 4
1 4 5
4 2 3

输出 #1复制

5

说明/提示

N \le 1000,M \le 100000N≤1000,M≤100000

x \le N,y \le N,t \le 100000x≤N,y≤N,t≤100000

1.该题是使用到了并查集加排序。

2.建议使用快排,因为快排时间复杂度不高,不会时间超限。

3.然后就是普普通通的并查集了,这里我之前卡到10分,没过是因为我再并查集里面是这样写的。

然后大部分都提示我MLE了,我以为是快排出现了错误,但是我只交了快排的代码是没有出现MLE的,我就找了一下,觉得可能这部分可以再优化一下。改成了下面这样子:

 

提交上去就全部AC了。

4.然后就是暴力去找是不是在一个集合,是不会出错的。

 

 代码如下:

#include<stdio.h>
#define N 1000+10
#define M 100010
typedef struct node
{
	int u;
	int v;
	int t;
}NODE;
NODE e[M]={0};
int n,m,k[N];
int quicksort(int left,int right)
{
	NODE t,temp=e[left];
	int i=left,j=right;
	if(left>right) return 0;
	while(i<j)
	{
		while(i<j&&temp.t<=e[j].t) j--;
		while(i<j&&temp.t>=e[i].t) i++;
		if(i<j)
		{
			t=e[i];e[i]=e[j];e[j]=t;
		}
	}
	e[left]=e[i];
	e[i]=temp;
	quicksort(left,i-1);
	quicksort(i+1,right);
}

int getf(int x)
{
	if(x==k[x]) return x;
	else return getf(k[x]);
}

int merge(int a,int b)
{
	int p,q;
	p=getf(a);
	q=getf(b);
	if(p!=q)
	{
		k[q]=k[p];
	}
}

int pd()
{
	int i,c=0;
	for(i=1;i<=n;i++)
		if(k[i]==i) c++;
	return c;
}

int main()
{
	int i;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
	{
		k[i]=i;
	}
	for(i=0;i<m;i++)
	{
		scanf("%d%d%d",&(e[i].u),&(e[i].v),&(e[i].t));
	}
	quicksort(0,m-1);
//	puts("after sorting:");
//	for(i=0;i<m;i++)
//		printf("%d %d %d\n",e[i].u,e[i].v,e[i].t);
	for(i=0;i<m;i++)
	{
		merge(e[i].u,e[i].v);
		if(pd()==1) 
		{
			printf("%d\n",e[i].t);
			break;
		}
	}
	if(i>=m) printf("-1\n");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值