解题报告:POJ_1703Find them, Catch them 并查集

Description

The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, the police first needs to identify which gang a criminal belongs to. The present question is, given two criminals; do they belong to a same clan? You must give your judgment based on incomplete information. (Since the gangsters are always acting secretly.)

Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds:

1. D [a] [b]
where [a] and [b] are the numbers of two criminals, and they belong to different gangs.

2. A [a] [b]
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang.

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case begins with a line with two integers N and M, followed by M lines each containing one message as described above.

Output

For each message "A [a] [b]" in each case, your program should give the judgment based on the information got before. The answers might be one of "In the same gang.", "In different gangs." and "Not sure yet."

Sample Input

1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4

Sample Output

Not sure yet.
In different gangs.
In the same gang.


类型:并查集

 

题意:

背景就是一个城市里两个组织,n个罪犯,每个罪犯都属于这个两个组织中的一个,知道一些罪犯不是属于同一个组织,问你某两个罪犯之间的关系

T组数据,n个人,m次请求

每次请求开始一个大写字母A或D

A表示询问你后面两个人的关系,输出有三种

D表示后面两个人不属于同一个组织。

 

思路:

我们知道每两个人之间的关系有三种,不确定,是同一组织,不是同一组织。

那么每个人有个状态,属于组织A,或者属于组织B。

那么对应每个人,我们用i表示组织A,i+Di(Di(different)为数据的最大规模)表示组织B。

每次知道A,B不是属于同一组织时:我们就把A的集合与B+Di的集合合并;同时将B的集合与A+Di的集合合并。

每次询问A,B的关系,如果A的根等于B+Di的根则表示属于不同组织;如果A的根等于B的根表示属于同一组织,否则就是不确定了

 

AC代码:


#include<cstdio>
#include<cstring>
#include<algorithm>

#define Di 100000

using namespace std;

int root[200005];

int find(int x)
{
    if(x!=root[x])
        root[x]=find(root[x]);//路径压缩递归
    return root[x];
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        n+=Di;
        for(int i=1;i<=n;i++)
            root[i]=i;
        while(m--)
        {
            int a,b;
            char c[10];
            scanf("%s%d%d",c,&a,&b);
            if(c[0]=='D')
            {
                int r1=find(a),r2=find(b+Di);
                if(r1!=r2)
                    root[r1]=root[r2];
                r1=find(a+Di),r2=find(b);
                if(r1!=r2)
                    root[r2]=root[r1];
            }
            else
            {
                if(find(a)==find(b))
                    printf("In the same gang.\n");
                else if(find(a)==find(b+Di))
                    printf("In different gangs.\n");
                else
                    printf("Not sure yet.\n");
            }
        }
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值