题解 洛谷 Luogu P1955 [NOI2015] 程序自动分析 并查集 离散化 哈希表 C++

题目

传送门

P1955 [NOI2015] 程序自动分析 - 洛谷 | 计算机科学教育新生态https://www.luogu.com.cn/problem/P1955

思路

主要用到的知识是并查集 (如何实现并查集,这里不赘述了)

若 xi = xj,则合并它们所在的集合。若 xi != xj,则 i 和 j 若在同一个集合,则 false

但是用最简单的并查集并不能 AC 本题,因为 i、j 相当大,数组承受不了

需要做离散化。用哈希表做离散化比较方便

细节

需要在处理完所有 = 情况时才能处理 != 情况,否则 != 会漏判后面再合并的情况

虽然每组测试数据是 n 行,但是每行可能有两个数据需要做离散化,所以 N 要开 2*5^10+

输入数据有多组,记得重置共享资源,或者干脆设为局部变量

更多细节见代码

代码

#include <unordered_map>
#include <vector>
#include <iostream>
using namespace std;
typedef pair<int, int> PII;
const int N = 200005;
int f[N], t, n;
int find(int a) { return f[a] == a ? a : f[a] = find(f[a]); } //并查集模板,没什么好说的
int main()
{
	ios::sync_with_stdio(false); //输入量不小,最好采用较快的 I/O 方式
	cin.tie(0);
	cin >> t;
	while (t--)
	{
		cin >> n;
		int sz = 2 * n, cnt = 0; //注意 2*n  //cnt 用于分配离散化的下标
		unordered_map<int, int> idx; //idx 用于离散化,通过 i、j 映射到它们离散化后的下标。操作全基于离散化后的下标
		vector<PII> v; //不等于的式子需要先存下来,后面再处理
		bool flag = true;
		for (int i = 0; i < sz; i++) f[i] = i; //重置共享资源
		while (n--)
		{
			int x, y, z;
			cin >> x >> y >> z;
			if (idx.count(x) == 0) idx[x] = cnt++; //没分配过下标的,新分配
			if (idx.count(y) == 0) idx[y] = cnt++;
			if (z) f[find(idx[x])] = find(idx[y]); //并查集模板,没什么好说的
			else v.push_back({ idx[x], idx[y] }); //存离散化后的下标
		}
		for (auto& x : v)
			if (find(x.first) == find(x.second))
			{ flag = false; break; }
		cout << (flag ? "YES\n" : "NO\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值