2016 UESTC Training for Data Structures C - 卿学姐与诡异村庄 并查集

C - 卿学姐与诡异村庄

Time Limit: 4500/1500MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit  Status

日复一日,年复一年,春去秋来。

卿学姐终于从天行廖那里毕业啦。出山的卿学姐首先来到了一个诡异的村庄。

在这个村庄中,只有两种人,一种是好人,一种是坏人。

好人只说真话,坏人只说假话。

村庄虚伪的平静由于卿学姐的到来,终于被打破了。

人们开始互相指控,每个人都会说另外一个人是否是好人。

卿学姐修行途中只学会了膜法,却不谙世事,所以卿学姐无法确认哪些人是好人,哪些人是坏人。

但是机智的卿学姐意识到可以通过这些人的指控来分辨。

现在告诉你村庄中每个人指控谁是否为好人,请问是否有个合理的分类能够符合所有的指控。

Input

第一行一个整数 N N,表示村庄总共有 N 个人,村民从 1 开始编号到 N

1N100000       

接下来 N N行,每行两个整数, ai,t     ,如果 t 1 ,那么说明第 i 个人认为第 ai 个人是好人。如果 t 2 ,那么说明第
i
个人认为第 ai 个人是坏人。

1aiN    

Output

如果存在一个好人坏人的分类能够满足所有的指控,那么输出"Time to show my power",否则输出"One face meng bi"

Sample input and output

Sample Input Sample Output
3
2 2
3 1
1 2
Time to show my power
3
2 2
3 2
1 2
One face meng bi

Hint

第一组样例中,如果1是好人,2和3都是坏人,就能解释得通这些指控


Source

2016 UESTC Training for Data Structures  Problem C


My Solution

并查集来维护,然后分好类

如果A说B是好人,把Ag 和 Bg 合并 他们是一伙的,都是good men; 把Ab 和 Bb 合并 他们是一伙的都是bad men

如果A说B是坏人,把Ag 和 Bb 合并 他们不是一伙的; 把Ab 和 Bg 合并 他们不是一伙的☺☺

然后笔者自己的处理方法就是father[2*maxn],之所以是2倍的maxn, 

是因为 father 1 ~ n 表示good men的初始集合,n+1 ~ 2*n表示bad men的初始集合

复杂度 O(n)

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 100000 + 8;
int father[2*maxn], _rank[2*maxn];
int n;

void DisjointSet(int n)
{
    for(int i = 1; i <= 2*n; i++){
        father[i] = i;
        father[i] = i;

    }
}


int find(int v){
    return father[v] = father[v] == v ? v : find(father[v]);
}

void _merge(int x, int y, bool bg){
    if(bg){//如果A说B是好人
        //把Ag Bg 合并
        int a = find(x), b = find(y);
        if(_rank[a] < _rank[b]){
            father[a] = b;
        }
        else{
            father[b] = a;
            if(_rank[b] == _rank[a]){
                ++_rank[a];
            }
        }
        //把Ab Bb 合并
        a = find(x+n), b = find(y+n);
        if(_rank[a] < _rank[b]){
            father[a] = b;
        }
        else{
            father[b] = a;
            if(_rank[b] == _rank[a]){
                ++_rank[a];
            }
        }
    }
    else{//如果A 说 B 是坏人
        //Ag 和 Bb 合并
        int a = find(x), b = find(y+n);
        if(_rank[a] < _rank[b]){
            father[a] = b;
        }
        else{
            father[b] = a;
            if(_rank[b] == _rank[a]){
                ++_rank[a];
            }
        }
        //Ab 和 Bg 合并
        a = find(x+n), b = find(y);
        if(_rank[a] < _rank[b]){
            father[a] = b;
        }
        else{
            father[b] = a;
            if(_rank[b] == _rank[a]){
                ++_rank[a];
            }
        }
    }
}

/* 如果1 说 1 是坏人 ☺
1
1 2

挺好玩的,如果A说自己是好人,那么ok
如果A说自己是坏人就懵逼了
郭爷的算法太牛逼了

*/

int main()
{
    #ifdef LOCAL
    freopen("a.txt", "r", stdin);
    #endif // LOCAL
    int a, t;
    scanf("%d", &n);
    DisjointSet(n);
    for(int i = 1; i <= n; i++){
        scanf("%d%d", &a, &t);
        _merge(i, a, 2-t);
    }
    bool _cerr = true;
    for(int i = 1; i <= n; i++){
        if(find(i) == find(i+n)){
            printf("One face meng bi");
            _cerr = false;
            break;
        }
    }
    if(_cerr) printf("Time to show my power");

    return 0;
}


Thank you!
                                                                                                                                               ------from  ProLights

你可能感兴趣的:(ACM,for,Data,并查集,Training,uestc,2016,structures)