Round Dance

该问题是一个图论应用,通过并查集建立人与他们记得的邻居之间的连接。最大组合数等于联通块的数量,最小组合数则要考虑是否存在环。如果找到环,则联通块不能与其他含有链的联通块组合,否则可以。代码中通过遍历和合并操作构建并查集,并检测环来计算最少和最多舞蹈组合数。
摘要由CSDN通过智能技术生成

Round Dance

题意:

现在有n个人,每个人记得一个邻居,每个人可以找两个人跳舞,跳舞最少要两个人,每个人都要跳舞,首先他要去找他记得的邻居a[i],然后还可以再选一个人连起来。问最少和最多可以有多少组舞蹈。

思路:

首先用并查集将a[i]和i连起来,然后每个联通块都是一组舞蹈,最多数量就是联通块的数量,因为每个人可以找两个人组合,所以环是无法再拉入人的,因为每个人都有两条边,而当一个联通块里面有链,它就可以与其他的包含链的联通块组合起来。所以最小数量就是成环的联通块,如果有存在链的联通块,就再加一,因为链可以合并起来。至于找链,只要a[a[i]] == i,那么这个联通块里面就有链,因为一个环的话每个人都会和两个不同的人连边,如果存在两个人连了两条边,就一定不存在环。

代码

int n, a[maxn];
int p[maxn];
 
int find(int x) {
	if (p[x] != x)	p[x] = find(p[x]);
	return p[x];
}
 
void merge(int x, int y) {
	if (find(x) == find(y))	return;
	p[find(x)] = find(y);
}
 
void solve() {
	cin >> n;
	for (int i = 1; i <= n; i++)	cin >> a[i];
	for (int i = 1; i <= n; i++)	p[i] = i;
	for (int i = 1; i <= n; i++)
		merge(i, a[i]);
	int mi = 0, mx = 0;
	int chain = 0;
	vector<int> e(n + 1, 0);
	for(int i = 1; i <= n; i ++ )
		if (a[a[i]] == i) {
			e[find(i)] = 1;
			chain = 1;
		}
	for (int i = 1; i <= n; i++) {
		if (find(i) == i) {
			if (!e[i])	mi++;
			mx++;
		}
	}
	cout << mi + chain << ' ' << mx << endl;
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方哲Beans

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值