poj 1703 Find them, Catch them (种类并查集)

看了半天才差不多有点看明白了关系的更新。


以下摘自博客:点击打开链接

 一道标准的关系型并查集题。普通的并查集是给几个同类的元素,而关系型并查集是给不同类的元素,然后求各个元素之间的关系。


       题目大意是:在一个城市里有两种不同的犯罪团伙。首先输入T表示有T组测试,然后输入N和M,表示有N个罪犯(编号从1到N)而且接下来有M个操作。操作分为两种:

1.D a b,表示编号为a和b的两个罪犯属于不同的犯罪团伙;

2.A a b,表示询问编号为a和b的两个罪犯是否是同一个犯罪团伙或者不确定。

对于每一个A操作,根据题意都要有相应的回答(输出)。


       接下来是解题思路:既然是用并查集来实现,我们可以定义一个整型数组表示当前节点与父节点的关系,偶数代表同类,奇数代表异类。初始化时每一个节点的父节点都为自己,关系数都为0。

每次进行查找一个节点的根节点时,都应该进行路径压缩,将沿途节点的父节点都修改为根节点,而关系数也应该对应地修改为与根节点的关系。该节点与根节点的关系数为该节点到根节点沿途所有节点的关系数之和(不包括该节点与当前父节点的关系数)。

进行合并操作时我们知道需要合并的两个原节点的关系为异类,如果这两个原节点的根节点相同(也就是说在同一个集合里面),那么我们可以直接忽略合并操作;如果这两个原节点的根节点不相同,那么应该对这两个原节点的根节点进行合并,合并后应该满足这两个原节点的关系为异类,我们需要并且只需要更新拥有新根的原根节点信息即可
。合并方式为将其中一个根节点的父节点修改为另一个根节点,而该根节点的关系数则应修改为两个原节点与原根节点的关系数之和加1,因为已知的信息是两个原节点的关系为异类,这样的操作是根据两个原节点之间关系以及两个原节点与对应根节点之间的关系得来的。


代码:


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e5+5;
int pre[maxn], rel[maxn];

void init(int n)
{
    for(int i = 1; i <= n; i++)
        pre[i] = i, rel[i] = 0;
}

int Find(int x)
{
    if(x == pre[x]) return x;
    int fa = pre[x];
    pre[x] = Find(pre[x]);
    rel[x] = (rel[x]+rel[fa])&1;    //
    return pre[x];
}

void join(int x, int y)
{
    int a = Find(x), b = Find(y);
    if(a != b)
    {
        pre[b] = a;
        rel[b] = (rel[x]-rel[y]+1)%2;   //
    }
}

int main(void)
{
    int n, q, t;
    cin >> t;
    while(t--)
    {
        scanf("%d%d", &n, &q);
        init(n);
        while(q--)
        {
            char cmd;
            int x, y;
            scanf(" %c%d%d", &cmd, &x, &y);
            if(cmd == 'D') join(x, y);
            else
            {
                int fa = Find(x), fb = Find(y);
                if(fa == fb)
                {
                    if(rel[x] == rel[y]) puts("In the same gang.");
                    else puts("In different gangs.");
                }
                else puts("Not sure yet.");
            }
        }
    }
    return 0;
}




Find them, Catch them
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 42926 Accepted: 13198

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.

Source



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值