题目链接:https://ac.nowcoder.com/acm/problem/17881
首先看到这道题,最简单的想法就是对于每一对相等的i,j通过并查集来建立联系,然后再去判断不相等的i,j是否有相等关系,有则不成立,没有就成立。
但是一看i和j的数据范围,头晕了。这么大的数据?????
那怎么办呢? 离散化嘛?(可是好烦啊,真的好烦啊,好复杂)
今天从毛毛雨学姐那学了一招。诈胡AC掉这道题。
对于1000000000数量级的i和j 我们将它,mod上一个较大,但是又没那么大的数。
比如mod上1e6+7 这样所有的i和j就强行缩小到我们可以接受的1e6 数量级了,再对这个范围进行并查集,应该就都没有问题了吧。
那么你该问了: 为什么可以这样做? 你这样做不对啊! 我可以举出反例!
如:
1
1 2 1
mod+1 mod+2 0
这样除余mod 以后就相当于
1
1 2 1
1 2 0
这样的输出肯定是 no
但是实际上的输出应该是yes
也就说明了这种方法是错误的
但是为什么这能称之为投机取巧的方法呢
我们来看一下他的数据量 N 是小于100000的, 那你把所有的数mod完以后 很难出现重数的情况,就算出现wa的情况,你改改这个mod,依然有大概率可以AC的。
并查集的基本操作我们就不谈了,上代码吧。

#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
#define ll long long
using namespace std;
#define close_stdin  ios::sync_with_stdio(false)
const int mod = 1e6 + 7;
int fa[1000007];
struct node {
    int x, y;
};
vector<node> vec;
//并查集常用操作 merge 与find
int find(int x) {  
    return(fa[x]==x?x:fa[x]=find(fa[x]));
}
void merge(int x, int y) { 
    fa[find(x)] = find(y);
}
void solve() {
    for (int i = 1;i <= mod;i++) {
        fa[i] = i;
    }
    int n;
    vector<node>vec;
    cin >> n;
    while (n--) {
        int i, j, e;
        cin >> i >> j >> e;
        i %= mod;j %= mod;
        if(!e){
            node temp;
            temp.x = i;temp.y = j;
            vec.push_back(temp);
        }
        else {
            merge(i, j);
        }
    }
    for (auto w : vec) {
        if (find(w.x) == find(w.y)) { cout << "NO\n";return; }
    }
    cout << "YES\n";
}
int main() {
    close_stdin;//只是为了让cin和printf一样快
    int T;
    cin >> T;
    while (T--) {
        solve();
    }
}