BZOJ 4195 程式自動分析【並查集+離散化】

神探小小迪發表於2018-09-24

Description

 在實現程式自動分析的過程中,常常需要判定一些約束條件是否能被同時滿足。

考慮一個約束滿足問題的簡化版本:假設x1,x2,x3,…代表程式中出現的變數,給定n個形如xi=xj或xi≠xj的變數相等/不等的約束條件,請判定是否可以分別為每一個變數賦予恰當的值,使得上述所有約束條件同時被滿足。例如,一個問題中的約束條件為:x1=x2,x2=x3,x3=x4,x1≠x4,這些約束條件顯然是不可能同時被滿足的,因此這個問題應判定為不可被滿足。

現在給出一些約束滿足問題,請分別對它們進行判定。

Input

輸入檔案的第1行包含1個正整數t,表示需要判定的問題個數。注意這些問題之間是相互獨立的。

對於每個問題,包含若干行:

第1行包含1個正整數n,表示該問題中需要被滿足的約束條件個數。

接下來n行,每行包括3個整數i,j,e,描述1個相等/不等的約束條件,相鄰整數之間用單個空格隔開。若e=1,則該約束條件為xi=xj;若e=0,則該約束條件為xi≠xj。

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

HINT

 在第一個問題中,約束條件為:x1=x2,x1≠x2。這兩個約束條件互相矛盾,因此不可被同時滿足。

在第二個問題中,約束條件為:x1=x2,x2=x1。這兩個約束條件是等價的,可以被同時滿足。

1≤n≤1000000

1≤i,j≤1000000000

題解:資料範圍比較大,必須先進行離散化處理。然後就是並查集了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn = 1000000;
struct node {
    int i, j;
    int e;
}a[maxn];
int fa[maxn], b[maxn<<1|1];
int get(int x){
    if(x == fa[x]) return x;
    return fa[x] = get(fa[x]);
}
void Merge(int x, int y){
    fa[get(x)] = get(y);
}
int main()
{
    int t, n;
    scanf("%d", &t);
    while(t--) {
        int id = 0;
        memset(fa, -1, sizeof fa);
        scanf("%d", &n);
        int flag = 1;
        for(int i = 1; i <= n; i++) {
            scanf("%d %d %d", &a[i].i, &a[i].j, &a[i].e);
            b[++id] = a[i].i, b[++id] = a[i].j;
        }
        sort(b+1, b+id+1);
        //tot = unique(b, b+id);
        for(int i = 1; i <= id; i++)
            fa[i] = i;
        for(int i = 1; i <= n; i++){
            if(a[i].e == 1){
                int x = lower_bound(b, b+id, a[i].i) - b;
                int y = lower_bound(b, b+id, a[i].j) - b;
                Merge(x, y);
            }
        }
        for(int i = 1; i <= n; i++){
            if(!a[i].e){
                int x = lower_bound(b, b+id, a[i].i) - b;
                int y = lower_bound(b, b+id, a[i].j) - b;
                if(get(x) == get(y)){
                    flag = 0;
                    break;
                }
            }
        }
        if(flag) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

 

相關文章