题意:有个n * m的元素周期表,如果我们有元素在(r1, c1), (r1, c2), (r2, c1),那们我们可以产生(r2, c2)元素。
给定q个元素的坐标,求最少放置多少个元素,使得棋盘上拥有n * m个元素。
分析:左边是n个行号,右边是m个列号,我们产生的每个元素都是一个行号和一个列号连边,我们要使得这个二分图变成完全二分图,
即总共有n * m条边。我们只需要将每个独立的连通块合并到一个集合,那么就是答案,合并的操作次数是连通块个数减1。
重点:我们要把所有的连通块合并到一个集合。这是化学反应产生的结果。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 400005;
int p[N];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
int n, m, q;
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n + m; ++i) p[i] = i;
int r, c;
for (int i = 1; i <= q; ++i)
{
scanf("%d%d", &r, &c);
c += n;
p[find(r)] = find(c);
}
int res = 0;
for (int i = 1; i <= n + m; ++i)
{
if (p[i] == i)
++res;
}
printf("%d\n", res - 1);
return 0;
}