Files
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

59 lines
1.7 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 1000 * 1000 + 10, M = N << 1;
int n, m;
// 二维转一维的办法,坐标从(1,1)开始
int get(int x, int y) {
// m为列宽
return (x - 1) * m + y;
}
struct Edge {
int a, b, c;
const bool operator<(const Edge &t) const {
return c < t.c;
}
} edge[M];
int el;
// 并查集
int p[N];
int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
// 先连1的边,再连2的边
void create_edges() {
for (int i = 1; i <= (n - 1) * m; i++) // 前n-1行的每个点,都可以向下引一条边权为1的边
edge[el++] = {i, i + m, 1}; // i -> i+m,边权为1
for (int i = 1; i <= n * m; i++) { // 向右引边,注意最后一列不能向右引边
if (i % m == 0) continue; // 最后一列放过
edge[el++] = {i, i + 1, 2}; // i->i+1,边权为2
}
// 因为加进去就是按边权由小到大录入的,所以不用再排序了
}
int main() {
cin >> n >> m;
// 建边
create_edges();
// 并查集初始化
for (int i = 1; i <= n * m; i++) p[i] = i;
int x1, y1, x2, y2;
// 利用二维转一维办法,将(x,y)映射成节点编号
// 某些点之间已经有连线了=> 标识这些点已在并查集中
while (cin >> x1 >> y1 >> x2 >> y2) {
int a = get(x1, y1), b = get(x2, y2);
p[find(a)] = find(b);
}
int res = 0; // 用Kruskal算法即可
for (int i = 0; i < el; i++) {
int a = find(edge[i].a), b = find(edge[i].b), c = edge[i].c;
if (a != b) p[a] = b, res += c;
}
cout << res << endl;
return 0;
}