1. 程式人生 > >【刷題】BZOJ 4195 [Noi2015]程序自動分析

【刷題】BZOJ 4195 [Noi2015]程序自動分析

並查集 script dep getch ear inline 連續 har ras

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

Solution

水題一道
由於等號具有連續性,所以先處理所有相等的限制,用並查集維護哪些是相等的
然後判斷不等號,如果有不等號兩邊在同一並查集內,顯然就不行

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define REP(a,b,c) for(register int a=(b),a##end=(c);a<=a##end;++a)
#define DEP(a,b,c) for(register int a=(b),a##end=(c);a>=a##end;--a)
const int MAXN=400000+10;
int T,n,fa[MAXN],lt;
std::vector<int> V;
std::map<int,int> M;
struct node{
    int x,y,opt;
    inline bool operator < (const node &A) const {
        return opt>A.opt;
    };
};
node limit[MAXN];
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void discretization()
{
    V.clear();M.clear();
    REP(i,1,n)V.push_back(limit[i].x),V.push_back(limit[i].y);
    std::sort(V.begin(),V.end());
    V.erase(std::unique(V.begin(),V.end()),V.end());
    REP(i,0,V.size()-1)M[V[i]]=i+1;lt=V.size();
    REP(i,1,n)limit[i].x=M[limit[i].x],limit[i].y=M[limit[i].y];
}
inline int found(int x)
{
    if(fa[x]!=x)fa[x]=found(fa[x]);
    return fa[x];
}
int main()
{
    read(T);
    while(T--)
    {
        read(n);
        REP(i,1,n)
        {
            int x,y,opt;read(x);read(y);read(opt);
            limit[i]=(node){x,y,opt};
        }
        discretization();
        std::sort(limit+1,limit+n+1);
        REP(i,1,lt)fa[i]=i;
        int mk=1;
        REP(i,1,n)
        {
            int u=limit[i].x,v=limit[i].y;
            if(limit[i].opt)fa[found(u)]=found(v);
            else if(found(u)==found(v))
            {
                mk=0;
                break;
            }
        }
        puts(mk?"YES":"NO");
    }
    return 0;
}

【刷題】BZOJ 4195 [Noi2015]程序自動分析