1 条题解
-
0
重建元素矩阵
tag
并查集,图论
题意简述
给你一个 的网格图,一开始有 个格子上被标记。对于任意两行两列,如果交汇的四个格子中有三个被标记,那么第 个会被自动标记。问你至少需要手动标记几个格子,使得整个矩形内的格子都被标记。
题解思路
对于任意两行两列,如果交汇的四个格子中有三个被标记,那么第 个会被自动标记。如果从图论的角度出发,我们可以把每个行和列看成一个点,交汇处的点看作边,那么实际上,对于第四个点的生成,实际上是四个点都位于一个连通块中。最后要让图上所有的格子都有点,实际上是要让所有的行,列都处于一个连通块中。每次操作,添加一个点,实际上就是把 行和 列所在的连通块合并。那么最少的操作次数就是目前有的连通块数量-1(即全部合并花费的次数)。
参考代码
struct DSU { std::vector<int> f, siz; DSU() {} DSU(int n) { init(n); } void init(int n) { f.resize(n); std::iota(f.begin(), f.end(), 0); siz.assign(n, 1); } int find(int x) { while (x != f[x]) { x = f[x] = f[f[x]]; } return x; } bool same(int x, int y) { return find(x) == find(y); } bool merge(int x, int y) { x = find(x); y = find(y); if (x == y) { return false; } siz[x] += siz[y]; f[y] = x; return true; } int size(int x) { return siz[find(x)]; } }; signed main() { IOS; int n, m, q; cin >> n >> m >> q; DSU dsu(n + m + 1); for(int i = 1; i <= q; i ++) { int x, y; cin >> x >> y; dsu.merge(x, y + n); } int ans = 0; for(int i = 1; i <= n + m; i ++) ans += dsu.f[i] == i; cout << ans - 1 << '\n'; return 0; }
信息
- ID
- 216
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 9
- 已通过
- 3
- 上传者