/*
translation:
已知所有元素要么属于第一个集合,要么属于第二个集合,给出两种操作。第一种是D a b,表示
a,b两个元素不在一个集合里面。第二种操作是A a b,表示询问a,b两个元素是否在同一个集合
里面。如果不能确定的话打印not sure。否则给出答案。
solution:
并查集。
这道题有点类似poj1182(食物链),两题的关键点都在于如何维护不同集合的关系。并查集的功能
正好与之相反,是维护相同集合间的关系。如何用并查集来实现不同集合的维护呢?方法是改变集
内元素的类型。本来unite(a,b)表示a,b属于同一个集合,现在用unite(a,b+n)来表示a,b属
于不同集合,即a属于第一个集合,b属于第二个集合。同理unite(a+n,b)表示a属于第二个集合
b属于第一个集合。每次要D操作时,将所有可能都unite。
note:
*并查集维护不同集合间的关系
date:
2016.10.17
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e5 + 5;
int n, m;
int par[maxn*2], high[maxn*2];
void init(int n)
{
for(int i = 1; i <= n; i++)
{
par[i] = i;
high[i] = 0;
}
}
int getRoot(int x)
{
return par[x] == x ? x : par[x] = getRoot(par[x]);
}
void unite(int x, int y)
{
x = getRoot(x);
y = getRoot(y);
if(x == y) return;
if(high[x] < high[y]) par[x] = y;
else
{
par[y] = x;
if(high[x] == high[y]) high[x]++;
}
}
bool same(int x, int y)
{
return getRoot(x) == getRoot(y);
}
int main()
{
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
init(2*n);
char op; int a, b;
for(int i = 1; i <= m; i++)
{
scanf("\n%c%d%d", &op, &a, &b);
if(op == 'D')
{
unite(a, b+n);
unite(a+n, b);
}
else
{
if(same(a, b+n) || same(a+n, b)) printf("In different gangs.\n");
else if(same(a, b) || same(a+n, b+n)) printf("In the same gang.\n");
else printf("Not sure yet.\n");
}
}
}
return 0;
}
poj1703(并查集维护不同集合关系的方法)
最新推荐文章于 2024-07-07 22:17:49 发布