洛谷题目P1955 [NOI2015] 程序自动分析(并查集、离散化、哈希)

题目来源:https://www.luogu.com.cn/problem/P1955

`

define int long long

int p[1000010]; bool haveans = 0;
const int MOD = 998823;

int find(int x) {
if (x != p[x]) { p[x] = find(p[x]); }
return p[x];
}

struct POIS
{
int xi, xj, e;
}pois[100010];

bool cmp(const POIS& a, const POIS& b) {
if (a.e > b.e) { return true; }
else {
return false;
}
}//先把能合的都合完再找反驳

signed main() {
int t; cin >> t;
while (t--) {
int n; cin >> n; int MAXNUM = 0;
for (int i = 0; i < n; i++) {
int nxi, nxj; cin >> nxi >> nxj >> pois[i].e;
pois[i].xi = nxi % MOD;
pois[i].xj = nxj % MOD;
if (pois[i].xi > MAXNUM) { MAXNUM = pois[i].xi; }
if (pois[i].xj > MAXNUM) { MAXNUM = pois[i].xj; }
}
sort(pois, pois + n, cmp);
for (int i = 1; i <= MAXNUM; i++) {
p[i] = i;//记录最大用过的节点的N来初始化
}
for (int i = 0; i < n; i++) {
if (pois[i].e) {
int pxi = find(pois[i].xi); int pxj = find(pois[i].xj);
if (pxi != pxj) {
p[pxi] = pxj;//合并祖宗而非子节点本身
}
}
else {
if (find(pois[i].xi) == find(pois[i].xj)) {
cout << "NO" << endl; haveans = 1;
break;
}
}
}
if (!haveans) {
cout << "YES" << endl;
}
haveans = 0;
}
return 0;
}`

写完之后偷看了题解里佬们的代码、、发现大家都在用离散化、、、而我是在随便取模(www太菜了)
代码思路:显而易见的并查集,题目的标签挂了‘离散化’和‘哈希’,我感觉取模应该算是哈希吧。。

debug过程如下
第一次debug:光写出来了并查集,交上去发现不对,,突然想到如果读取一组数据查一次矛盾的话,只能查到前面已读取以及已合并的数据是否矛盾,如果后面又读一组数据后并进去,没法再判断它是否跟之前的‘!=’矛盾了,所以预读入数据并排序,先把能合并的全合并,再依次判谁谁不能合并
第二次debug:加入了MOD取模,原来的数据九次方太大了,开这么大的祖宗数组就会超
第三次debug:加入了MAXNUM用于记录目前用过的最大的序号,之前是拿n来对祖宗数组初始化的(初始化就是p[i]=i,自己是自己的祖宗),后来发现即使n=3有三组数据,但是也会涉及到6、9、11这种远大于3的序号,所以必须存储
第四次debug:突然发现并查集板子抄错了。。p[pois[i].xj] = pxi;错了,应该把祖宗节点合并啊啊啊,所以改成p[pxi] = pxj;,终于A了,普天同庆!

这道题目的遗留问题:去学一下离散化...(怎么记得好像学过的样子)

posted @ 2025-07-14 15:47  yubai111  阅读(57)  评论(0)    收藏  举报