UESTC 1586 可以说是非常豹笑了 2-SAT+并查集

可以说是非常豹笑了

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)


Submit  Status
title


你总是说:“可以说是非常豹笑了”


可是非常豹已经很累了,


非常豹不想笑,


它想念自己的家人,


而不是被你逼着笑。


你关心过这些吗?


没有!你只关心你自己。


Input

第一行输入一个正整数N(2<=N<=1000000)表示总天数,一个正整数M(1<=M<=1000000)表示给出的关系数。


接下来M行,每行三个整数T(T=1 or 0)、A、B(1<=A,B<=N)。T=1表示在第A天和第B天非常豹的表情一样、T=0表示在第A天和第B天非常豹的表情不一样。


非常豹在一天里要么笑了,要么没笑。


Output

输出 'YES’ 如果输入是可能的话;


输出'NO' 如果无论怎样都不可能满足输入给出的关系。


Sample input and output

Sample Input Sample Output
2 2
1 1 2
0 2 1
NO
2 2
1 1 1
0 2 1
YES


Hint

没有多组数据


Source

2017 UESTC Training for Data Structures

UESTC 1586 可以说是非常豹笑了


My Solution

题意:n个数,m个关系,每个关系表示T==1则a、b两数相同,T == 0则a、b两数不同。
要求判断关系是否没有矛盾。


2-SAT+并查集
有一个大小为2*n的并查集,
如果a、b天相同,则把a和b,以及a+n和b+n,合并,
如果a、b天不同,则把a和b+n,以及a+n和b,合并,
然后i= 1 ~ n,扫一遍,如果 a和a+n在同一颗树中,则相矛盾,
因为不可能那天表情即一样又不一样,答案为NO,
反正为 YES
复杂度 O(2*n)


#include 
#include 

using namespace std;
typedef long long LL;
const int MAXN = 1e6 + 8;

int father[2*MAXN], _rank[2*MAXN];
inline void init(int n)
{
    for(int i = 0; i <= n; i++){
        father[i] = i;
        _rank[i] = 0;
    }
}
inline int _find(int x)
{
    return father[x] = father[x] == x ? x : _find(father[x]);
}
inline void _merge(int x, int y)
{
    int a = _find(x), b = _find(y);
    if(a == b) return;
    else{
        if(_rank[a] < _rank[b]){
            father[a] = b;
        }
        else{
            father[b] = a;
            if(_rank[a] == _rank[b]){
                _rank[a]++;
            }
        }
    }

}

int main()
{
    #ifdef LOCAL
    freopen("n.txt", "r", stdin);
    //freopen("n.out", "w", stdout);
    int T = 2;
    while(T--){
    #endif // LOCAL
    //ios::sync_with_stdio(false); cin.tie(0);

    int n, m, i, j, t, x, y;
    scanf("%d%d", &n, &m);
    init(2*n);
    for(i = 1; i <= m; i++){
        scanf("%d%d%d", &t, &x, &y);
        if(t){
            _merge(x, y);
            _merge(x + n, y + n);
        }
        else{
            _merge(x, y + n);
            _merge(x + n, y);
        }
    }
    bool ans = true;
    for(i = 1; i <= n; i++){
        if(_find(i) == _find(i + n)){
            ans = false;
            break;
        }
    }
    if(ans) puts("YES");
    else puts("NO");


    #ifdef LOCAL
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}


  Thank you!

                                                                                                                                             ------from ProLights

你可能感兴趣的:(图论:2-SAT,数据结构:并查集,UESTC,OJ,算法的艺术)