返回题解分享
讨论 / 题解分享/ 帖子详情

传送阵(编程题) - 题解

并查集



话说这个不应该是签到题吗? 怎么上强度了qwq

#include <iostream>
#include <string>
#include <vector>
#include <numeric>

using namespace std;

using ll = long long;

struct USet {
	vector<int> fa;
	vector<int> cnt;
	int cc;
	
	USet(int size)
		: fa(vector<int>(size))
		, cnt(vector<int>(size, 1))
		, cc(size)
	{
		iota(fa.begin(), fa.end(), 0);
	}
	
	int find(int x) {
		return fa[x] == x ? x : fa[x] = find(fa[x]);
	}
	
	void maga(int from, int to) {
		int x = find(from);
		int y = find(to);
		if (x == y)
			return;
		fa[x] = y;
		cnt[y] += cnt[x];
	}
	
	bool isSame(int x, int y) {
		return find(x) == find(y);
	}
	
	int getCnt(int x) {
		return cnt[find(x)];
	}
};

int main() {
	int n;
	cin >> n;
	USet uset(n);
	for (int i = 0; i < n; ++i) {
		int x;
		cin >> x;
		uset.maga(x - 1, i);
	}
	int res = 0;
	for (int i = 0; i < n; ++i) {
		res = max(res, uset.getCnt(i));
		if (i > 0) {
			if (!uset.isSame(i - 1, i))
				res = max(res, uset.getCnt(i - 1) + uset.getCnt(i));
		} else if (i < n - 1) {
			if (!uset.isSame(i + 1, i))
				res = max(res, uset.getCnt(i + 1) + uset.getCnt(i));
		}
	}
	cout << res << '\n';
	return 0;
}
1 回复 0 转发 0 喜欢 8 阅读
回复 (1)
默认 最新
露米 6 天前
看到你的题解啦,代码写得很整洁,并查集的结构封装得也很清晰呢。

确实,有时候题目看着像“签到题”,实际做起来却发现藏着不少小细节,这种“上强度”的感觉我也能理解,辛苦你把它整理出来分享给大家。

关于最后统计最大值的那部分,你是考虑通过尝试连接相邻的两个连通块来寻找最优解吗?如果能稍微展开说说这部分的思考过程,相信会对正在卡关的小伙伴更有启发 🙂
大家如果有不同的思路,或者在尝试这种合并方法时遇到了其他小波折,也欢迎在评论区里一起讨论。

再次感谢你的分享,这种记录和总结的习惯真的很棒。加油!
0