AcWing4866. 最大数量

 这个是本周AcWing的周赛题,但是我完全被第二题就绊住了,也没怎么看第三题。虽然看了我也写不出来。

看了一下y总的讲解,现在记录一下这道题的解法。

刚才又看了一下讲解,原来第i个要求中添加i条边不是在i-1个需求的基础上再添加i-1条边,而且相对于最开始的空图添加i条边,并且满足前i个需求。要注意这一点!

然后我们来分析题目:题目说的是让两个点连通,联通的话可以认为这两个集合属于同一个集合。那么我们可以用并查集维护若干个集合,如果两个点是联通的,那么这两个点就会属于同一个集合。

好,如果目前需要联通的两个点属于两个集合,那么需要几条边来完成对这两个点的联通呢?因为一个集合内部的所有点都是互相连通的,所以如果让两个点联通,相当于让这两个集合联通,那么只需要一条边就可以实现两个集合的联通。这就相当于两个村庄之间的建交,只要保证2个村庄中各出一个人,这两个人熟悉起来了,其他人也就全部能联系上了。

所以,这里有一个规律:让任意两个点联通,最多需要1条边。

那么再考虑一件事:如果我们现在有x条边,我们最多能让多少个集合联通呢?答案是x+1个集合。

 

题目中还有1个要求,需要保证所有点的度数的最大值最大,也就是说在所有的集合中找到一个点,这个点和最多的点有边相连。那么我们如何保证在指定条边的情况下,某个点的度数能够达到最大呢?很明显,让这个点成为中心,让每一条边都是由他辐射出去的。

很明显,两个集合都是完全联通的集合,但是第二个图中的最大度数为5.所以我们为了保证度数的最大值是最大的 ,那么就要保证这个集合内部的连接情况是菊花图式的。那么这个集合中的最大度数是多少呢?目前有x个点,那么最大度数就是x-1;

因为题目也不要求输出具体的边,所以我们只要考虑这个最大度数是多少,然后输出就好了。

好了,预备知识全部整理完毕,现在就针对一个具体的请求i进行分析吧。

首先对于第i个请求中的x和y,我们可能存在两种情况:

1.x和y本就是一个集合内部的,那么他们本来就是联通的,不需要添加边了,剩下一条边。这条边我们可以用来干嘛呢,当然是去和其他的集合进行联通了。

2.x和y分属于两个集合,那么就得在这两个集合中添加一条边,使得这两个集合进行合并了。那么这次的联通没能攒下这条边。

我们在每轮进行联通的时候都会统计一下当前多余的边的情况,然后看看这些多余的边还能联通几个其他的未联通的集合。

所以是不是很清晰的思路了?首先让这两个点x和y进行联通,然后统计目前多余的边,用这些边去联通其他的集合,而且联通的这些集合最好是集合内的元素越多越好,这样才能保证我们的最大度数越大。当所有多余的边都用光了,或者已经没有没联通的集合了,那么我们就看看这个集合中一共有多少个元素。最大的度数肯定是这个最大集合中的一个元素作为中心,从它向集合中的所有其他元素进行连线,所以最大度就是n-1.

这个题每一问都是独立的,所以暗示我们什么呢?就是上一次的连法和这一次的可能不同,但是我们可以借鉴上一次的。所以我们才可以把所有的点归到一个集合中,再分配边,以此来构造最大的度。

那么代码出来了:

int find(int a){
	if(p[a] != a) p[a] = find(p[a]);
	return p[a];
}
int main(){
	int n, d;
	scanf("%d%d", &n, &d);
	for(int i = 1; i <= n; i++){
		p[i] = i;
		s[i] = 1;   //不同集合里面的元素数量 
	}
	int cnt = 0;  //多余的边 
	for(int i = 0; i < d; i++){
		int a, b;
		scanf("%d%d", &a, &b);
		a = find(a);
		b = find(b);
		if(a != b){
			p[a] = b;
			s[b] += s[a];  //合并这两个集合 
		}else{
			cnt++;   //这两个点已经联通了,所以多余了一条边 
		}
		int tt = 0;
		for(int i = 1; i <= n; i++){
			if(find(i) == i) sz[tt++] = s[i];   //每个集合中元素的个数
		}
		sort(sz, sz + tt, greater<int>());  //把元素个数从大到小排序 
		int sum = 0;
		//cnt条边可以连接cnt+1个集合 
		for(int i = 0; i < tt && i < cnt + 1; i++){  //将元素个数最大的几个集合进行连接 
			sum += sz[i];
		}
		cout<<sum - 1<<endl;  // 这么多元素,所以度数等于元素数-1 
		
	}
	return 0;
} 

参考:主播,我们是不是你带过的最差的一届学生?AcWing杯 - 第92场周赛_哔哩哔哩_bilibili

就写到这了,昨天被y总和y嫂的爱情狠狠嗑到,其实都没好好听分析。

马上去打leetcode周赛,这次争取做完两题/(ㄒoㄒ)/~~

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值