一道比较好的并查集题目:Gangs
题目描述
描述
1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。
而且有一点是肯定的,就是A的朋友的朋友是A的朋友;A的敌人的敌人也是A的朋友。
两个强盗是同一伙的当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你至多有多少个强盗团伙。
输入
输入的第一行为N(2<=N<=1000),表示强盗的个数(从1编号到N)。
第二行M(1<=M<=100000),表示信息条数。
以下M行,每行可能是F p q或是E p q,分别表示p和q是朋友,或是敌人。
假设输入不会产生矛盾
输出
输出只有一行,表示最大可能的团伙数。
样例输入
6
4
E 1 4
F 3 5
F 4 6
E 1 2
样例输出
3
解答
代码
#include <iostream>
using namespace std;
int a[1001] = {0};
int b[1001][1001] = {0};
int father(int n) {
if (a[n] == -1) {
return n;
} else
return father(a[n]);
}
int hb(int x, int y) {
int n, m;
n = father(x);
m = father(y);
if (n < m) {
a[m] = n;
} else {
a[n] = m;
}
return 0;
}
int main() {
int n, m;
int i, j, k;
char c;
int x, y, z, p;
cin >> n >> m;
for (i = 1; i <= 1001; i++) {
a[i] = -1;
}
for (i = 1; i <= m; i++) {
cin >> c >> x >> y;
if (c == 'E') {
b[y][x] = 1;
b[x][y] = 1;
}
if (c == 'F') {
hb(x, y);
}
}
for (i = 1; i <= n; i++)
for (j = 1; j < i; j++) {
if (b[i][j]) {
for (k = 1; k <= n; k++) {
if (b[j][k] && k < i) {
hb(k, i);
}
}
}
}
int s = 0;
for (i = 1; i <= n; i++) {
if (a[i] == -1) s++;
}
cout << s;
system("pause");
return 0;
}