看了半天才差不多有点看明白了关系的更新。
以下摘自博客:点击打开链接
一道标准的关系型并查集题。普通的并查集是给几个同类的元素,而关系型并查集是给不同类的元素,然后求各个元素之间的关系。
题目大意是:在一个城市里有两种不同的犯罪团伙。首先输入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;
}
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 42926 | Accepted: 13198 |
Description
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
Output
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