POJ 1703 Find them, Catch them


题意:

有两个帮派龙帮,蛇帮,警察需要验证嫌疑人属于哪个帮派。需要解决的问题是,给出两个嫌疑人,你必须通过不完全的信息,判断他们是否属于一样帮派。

有 N ( 1 < N < 100000 ) 个嫌疑人,标号 1 到 N,至少有一个属于龙帮,一个属于蛇帮。有 M ( 1 < M < 100000 ) 条信息,有两种类型的信息,

1.D a b 意味着 a 和 b 属于不同帮派

2.A a b 查询 a 和 b 是否属于一个帮派


输入:

第一行测试次数,第二行两个整数,N,M 意味着有 N 个嫌疑人和 M 条信息

接下来的M行输入信息


输出:

对于每个 A a b 的输出,有三种可能,“不能确定”,“不在一个帮派”,“在一个帮派”,输出一种。


比如输入:

1

5 5

A 1 2

D 1 2

A 1 2

D 2 4

A 1 4


比如输出:

Not sure yet.

In different gangs.

In the same gang.


思路:

并查集,代码很清楚。


#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
#define MAX_SIZE 100010
#define UNKOWN -1

int others[MAX_SIZE]; // 非该嫌疑人本人的帮派(干脆叫该嫌疑人的敌对帮派吧)
int parents[MAX_SIZE]; 

int find_gang( int suspect ){
    if( suspect != parents[suspect] )
        parents[suspect] = find_gang( parents[suspect] );
    return parents[suspect];
}

// 简单的合并了下
void merge_gang( int suspect_a, int suspect_b ){
    int gang_of_a = find_gang( suspect_a );
    int gang_of_b = find_gang( suspect_b );
    parents[gang_of_a] = gang_of_b;
}


// 将两个嫌疑人分配到不同的帮派里面
void differ( int suspect_a, int suspect_b ){
    // 若是 a 的敌对帮派未知,那么僵敌对帮派设为 b
    if( others[suspect_a] == UNKOWN ){
        others[suspect_a] = suspect_b;
    }
    else{
        // a 的敌对帮派已知,那么就将 b 与 a 的敌对帮派归为一类
        merge_gang( others[suspect_a], suspect_b );
    }
    
    // 若是 b 的敌对帮派未知,那么僵敌对帮派设为 a
    if( others[suspect_b] == UNKOWN ){
        others[suspect_b] = suspect_a;
    }
    else{
        // b 的敌对帮派已知,那么就将 a 与 b 的敌对帮派归为一类
        merge_gang( others[suspect_b], suspect_a );
    }
}


void answer( int suspect_a, int suspect_b ){
    if( others[suspect_a] == UNKOWN || others[suspect_b] == UNKOWN ){
        cout << "Not sure yet.\n";
        return;
    }
    int gang_of_a = find_gang( suspect_a );
    int gang_of_b = find_gang( suspect_b );
    int other_gang_of_a = find_gang( others[suspect_a] );
    int other_gang_of_b = find_gang( others[suspect_b] );
    if( gang_of_a == gang_of_b ){
        cout << "In the same gang.\n";
        return;
    }
    // 若是 a 的帮派和 b 的敌对帮派一致,证明 a,b 不在一个帮派
    if( gang_of_a == other_gang_of_b ){
        cout << "In different gangs.\n";
        return;
    }
    cout << "Not sure yet.\n";
}

int main(){
    int test_num;
    scanf( "%d", &test_num );
    while( test_num-- ){
        memset( others, UNKOWN, sizeof( others ) );
        int suspect_num, msg_num;
        scanf( "%d%d", &suspect_num, &msg_num );

        for( int i = 0; i <= suspect_num; ++i )
            parents[i] = i;

        while( msg_num-- ){
            char ch;
            int suspect_a;
            int suspect_b;
            scanf("\n%c%d%d", &ch, &suspect_a, &suspect_b);
            if( ch == 'D' ){
                differ( suspect_a, suspect_b );
            }
            else{
                answer( suspect_a, suspect_b );
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值