Description

在实现程序自动分析的过程中, 常常需要判定一些约束条件是否能被同时满足.

考虑一个约束满足问题的简化版本: 假设 \(x_1, x_2, x_3, \ldots\) 代表程序中出现的 变量, 给定 \(n\) 个形如 \(x_i = x_j\)\(x_i \neq x_j\) 的变量相等/不等的约束条件, 请判定是否可以分别为每一个变量赋予恰当的值, 使得上述所有约束条件同时被满足. 例如, 一个问题中的约束条件为:\(x_1 = x_2, x_2 = x_3, x_3 = x_4, x_1 \neq x_4\), 这些 约束条件显然是不可能同时被满足的, 因此这个问题应判定为不可被满足.

现在给出一些约束满足问题, 请分别对它们进行判定.

Input

输入文件的第 \(1\) 行包含 \(1\) 个正整数 \(T\), 表示需要判定的问题个数. 注意这些问题 之间是相互独立的.

对于每个问题, 包含若干行:

\(1\) 行包含 \(1\) 个正整数 \(n\), 表示该问题中需要被满足的约束条件个数.

接下来 \(n\) 行, 每行包括 \(3\) 个整数 \(i, j, e\), 描述 \(1\) 个相等/不等的约束条件, 相邻整数之间用单个空格隔开. 若 \(e = 1\), 则该约束条件为 \(x_i = x_j\); 若 \(e = 0\), 则该约束条件为 \(x_i \neq x_j\).

Output

输出文件包括 \(T\) 行.

输出文件的第 \(k\) 行输出一个字符串 YES 或者 NO (不包含引号, 字母全部大写),YES 表示输入中的第 \(k\) 个问题判定为可以被满足,NO 表示不可被满足.

Sample Input

2
2
1 2 1
1 2 0
2
1 2 1
2 1 1

Sample Output

NO
YES

Data Range

对于所有数据, 满足:\(1 \leq n \leq 10^6, 1 \leq i, j \leq 10^9\)

Explanation

此题可以强行离线, 先搞定所有的相等条件, 然后判断不等条件是否可以满足.

当然也可以用某年 NOIP 的 “食物链” 的做法维护并查集偏移量, 也就是强制在线的做法, 虽然这种做法代码量并不会高出多少.

由于本蒟蒻很懒所以就只写了强行离线的做法.

Source Code


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <set>
#include <algorithm>

using namespace std;
typedef long long lli;
const int maxn = 2000100;

class DisjointSet
{
public:
    int par[maxn];
    int n;
    int find(int p)
    {
        if (par[p] == p)
            return p;
        return par[p] = find(par[p]);
    }
    void join(int p, int q)
    {
        p = find(p);
        q = find(q);
        par[p] = q;
        return ;
    }
    void init(int n)
    {
        this->n = n;
        for (int i = 1; i <= n; i++)
            par[i] = i;
        return ;
    }
} djs;

int T, n;
int dat[maxn][3];
set<int> st;
int arr[maxn];

int search(int val)
{
    return lower_bound(arr + 1, arr + arr[0] + 1, val) - arr;
}

int main(int argc, char** argv)
{
    scanf("%d", &T);
    for (int idx = 1; idx <= T; idx++) {
        scanf("%d", &n);
        st.clear();
        for (int i = 1; i <= n; i++) {
            scanf("%d%d%d", &dat[i][0], &dat[i][1], &dat[i][2]);
            st.insert(dat[i][0]);
            st.insert(dat[i][1]);
        }
        // Concatencating items, in order
        arr[0] = 0;
        for (set<int>::iterator i = st.begin(); i != st.end(); i++)
            arr[++arr[0]] = *i;
        // Joining items (forced offline)
        djs.init(arr[0]);
        for (int i = 1; i <= n; i++) if (dat[i][2] == 1) {
            int x = search(dat[i][0]),
                y = search(dat[i][1]);
            djs.join(x, y);
        }
        // Checking if correct
        bool correct = true;
        for (int i = 1; i <= n; i++) if (dat[i][2] == 0) {
            int x = search(dat[i][0]),
                y = search(dat[i][1]);
            x = djs.find(x);
            y = djs.find(y);
            if (x == y) {
                correct = false;
                break;
            }
        }
        printf("%s\n", correct ? "YES" : "NO");
    }
    return 0;
}