POJ 1703 Find them, Catch them
题目大意
有两个帮派,有N
个人,编号是1
- N
,有M
次询问,每次问两个人,然后又两个操作:
- 操作
A
,输出编号X
和编号Y
是否在同一阵营。 - 操作
D
,编号X
和编号Y
不是在同一个阵营。
保证数据的合法性。
思路
种类并查集比较模板的题目了,因为是有两个阵营,所以我们可以将原来的编号长度N
扩展成为长度2 * N
。我们将1
- N
长度内的集合设置为“朋友”关系, N + 1
- 2 * N
的长度内的集合设置成“敌人”关系。如果是“敌人”关系,我们就将X
与Y + N
和 Y与X + N
合并在一起。
询问的时候X
和Y
在一个阵营就表示是“朋友”关系,X
和Y + N
或者Y
和X + N
在一个阵营就代表是“敌人”关系,否则就是不清楚。
参考代码:
#include <iostream>
#define endl "\n"
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 7;
const int inf = 2147483647;
int fa[maxn];
int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
x = find(x), y = find(y);
if (x != y) fa[x] = y;
}
void solve()
{
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= 2 * n; i++) fa[i] = i;
while (m--)
{
char op[2];
int x, y;
scanf("%s%d%d", &op, &x, &y);
int xx = find(x), yy = find(y);
if (op[0] == 'A'){
if (xx == yy) cout << "In the same gang." << endl;
else if (xx == find(y + n)) cout << "In different gangs." << endl;
else cout << "Not sure yet." << endl;
}
else merge(xx, y + n), merge(yy, x + n);
}
}
signed main()
{
int t;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}