「Codeforces 1012B」Chemical table - 并查集

版权声明:禁止商业用途,如需转载请注明原文出处:https://hyp1231.github.io 或者 https://blog.csdn.net/hyp1231/article/details/81295464

建议访问原文出处,获得更佳浏览体验。
原文出处:https://hyp1231.github.io/2018/07/31/20180731-cf1012b/

题意

给定一个 n × m 的矩阵,其中 q 个位置已经被填充。
有一条规则,如果 ( r 1 , c 1 ) ( r 1 , c 2 ) ( r 2 , c 1 ) 均被填充,则 ( r 2 , c 2 ) 也被填充。任何被其他三个位置生成的位置,也可以继续生成其他位置。问最少需要再人为填充多少元素,使矩阵被填满。

链接

Codeforces 1012B

题解

我们考虑自动填充的规则,又三个点自动生成第四个点。如果 ( r 1 , c 1 ) ( r 1 , c 2 ) ( r 2 , c 1 ) 均被填充,则可以看成:

  1. ( r 1 , c 1 ) r 1 c 1 被联系起来
  2. ( r 1 , c 2 ) r 1 c 2 被联系起来
  3. 1 , 2 c 1 c 2 被联系起来
  4. ( r 2 , c 1 ) r 2 c 1 被联系起来
  5. 3 , 4 r 2 c 2 被联系起来,即有 ( r 2 , c 2 ) 被填充

这两个模型是等价的。至此,我们把每个边的标号和每个列的标号都看成抽象图中的点,每个给出的点 ( r , c ) 看成一个关于点 r 和点 c 属于同一集合的声明。故我们可以使用并查集维护,计算出当前矩阵中独立集合的数量 N

考虑需要人工合并的次数(即认为填充元素的数目)。考虑当前矩阵中未被填充的点,人工填充这个点一定可以实现两个集合的合并,总集合数即减 1 。每次人工填充后均自动填充所有可以被自动填充的点。故 N 1 次人工填充后,将全部属于一个集合,矩阵被填满,所以原题的答案即为 N 1

代码

#include <iostream>
#include <algorithm>

typedef long long LL;

const int N = 200010;

int n, m, q;
int pre[N << 1], rank[N << 1];
bool vis[N << 1];

int find(int x) {
    return x == pre[x] ? x : pre[x] = find(pre[x]);
}

void merge(int x, int y) {
    int rx = find(x), ry = find(y);
    if (rx != ry) {
        if (rank[rx] == rank[ry]) {
            pre[ry] = rx;
            rank[rx]++;
        } else if(rank[rx] < rank[ry]) {
            pre[rx] = ry;
        } else {
            pre[ry] = rx;
        }
    }
}

int main() {
    std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);

    std::cin >> n >> m >> q;

    for (int i = 1; i <= m + n; ++i) {
        pre[i] = i;
    }   // 初始化并查集

    int r, c;
    for (int i = 0; i < q; ++i) {
        std::cin >> r >> c;
        c += n;     // 列的编号: 1 + n ~ m + n
        merge(r, c);
    }

    long long ans = 0;
    for (int i = 1; i <= m + n; ++i) {
        int root = find(i);
        if (!vis[root]) {
            vis[root] = true;
            ++ans;  // 找到新的连通块
        }
    }

    std::cout << ans - 1 << std::endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/hyp1231/article/details/81295464