2023-2024年度第四届全国大学生算法设计与编程挑战赛(秋季赛)

交流是一件很酷的事情

内存限制:512Mb

时间限制:1s

提交:6836

解决:621

题目描述

古老的王国中有 nn 个城市,这些城市之间由 mm 条道路相连接。现在又到了一年一度要举行交流会的时候,国王计划要在这些城市之间举行 kk 场交流会,每一场交流会在指定的两个城市间举行。

每个城市都有独一无二的思想,思想只有通过交流才能够流通,交流是一个相互并且可以传到的过程,比如说,如果城市 aa 和城市 bb 进行了交流,那么城市 aa 和城市 bb 就都拥有了对方的思想;如果城市 bb 和城市 cc 又有交流,那么城市 aa、bb、cc 就都有三份思想。

然而,你作为王国的军师,充分明白复习的重要性,在收到了国王的计划之后,你深知如果城市 aa 有了城市 bb 的思想,但是两个城市之间不能相互到达,即没有道路直接或者间接连接,那么他们就无法在交流会之后再次交流,在一段时间后他们就会忘记对方的思想。

国王想要知道在这些交流会很久之后,所有的城市中,最多能够有多少份思想、最少又能够有多少份思想。注意,每一个城市最初就有一个自己的想法。

输入

第一行两个整数 nn、mm,表示城市的数量和道路的数量。

接下来 mm 行,每行两个整数 uiui​、vivi​,表示城市 uiui​ 和 vivi​ 之间有一条道路相连接。

接下来一行一个整数 kk,表示交流会的数量。

接下来 kk 行,每行两个整数 xixi​、yiyi​,表示预计在城市 xixi​ 和城市 yiyi​ 之间举行一场交流会。

输出

输出一行两个整数 maxvmaxv 和 minvminv,表示城市最多的思想数量和最少的思想数量。

样例输入

8 6 1 3 1 4 2 7 3 5 3 6 3 8 5 1 3 1 8 2 3 2 7 4 6

样例输出

3 1

提示

数据规模与约束

对于 100%100% 的数据,2⩽n,m,k⩽2×105,1⩽ui,vi,xi,yi⩽n2⩽n,m,k⩽2×105,1⩽ui​,vi​,xi​,yi​⩽n,保证无重边无自环。

样例解释

所有交流会结束后,每座城市有的思想如下:

  • 城市 1:1、2、3、7、8
  • 城市 2:1、2、3、7、8
  • 城市 3:1、2、3、7、8
  • 城市 4:4、6
  • 城市 5:5
  • 城市 6:4、6
  • 城市 7:1、2、3、7、8
  • 城市 8:1、2、3、7、8

而在原图中,[1,3,8][1,3,8] 联通,[2,7][2,7] 联通,[4,6][4,6] 联通。

所以在足够长的时间过后,各个城市拥有的思想会维持在以下状态:

  • 城市 1:1、3、8
  • 城市 2:2、7
  • 城市 3:1、3、8
  • 城市 4:4、6
  • 城市 5:5
  • 城市 6:4、6
  • 城市 7:2、7
  • 城市 8:1、3、8

故城市最多有 3 份思想(城市 1、城市 3、城市 8),最少只有 1 份思想(城市 5)。



思路:维护两个并查集

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
typedef pair<int, int> PII;
typedef long long LL;

int n, m, k;
int fa[N], fa1[N];

void init() {
	for (int i = 1; i <= n; i ++ ) {
		fa[i] = i;
		fa1[i] = i;
	}
}

int find(int x) {
	return x == fa[x] ? fa[x] : fa[x] = find(fa[x]);
}

int find1(int x) {
	return x == fa1[x] ? fa1[x] : fa1[x] = find1(fa1[x]);
}

int main() {
	cin >> n >> m;
	init();
	
	int a, b;
	for (int i = 1; i <= m; i ++ ) {
		cin >> a >> b;
		a = find(a); b = find(b);
		fa[a] = b;
	}
	
	
	cin >> k;
	for (int i = 1; i <= k; i ++ ) {
		cin >> a >> b;
		a = find1(a); b = find1(b);
		fa1[a] = b;
	}
	
	map<pair<int, int>, int> mp; 
	
	for (int i = 1; i <= n; i ++ ) {
		mp[{find1(i), find(i)}] ++;
 	}
	
	int minNum = 0x3f3f3f3f, maxNum = 0;
	for (auto t : mp) {
		minNum = min(minNum, t.second);
		maxNum = max(maxNum, t.second);
	}
	
	cout << maxNum << " " << minNum;
	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值