1144. 连接格点,Kruskal算法,二维矩阵压缩为一维

有一个 m 行 n 列的点阵,相邻两点可以相连。

一条纵向的连线花费一个单位,一条横向的连线花费两个单位。

某些点之间已经有连线了,试问至少还需要花费多少个单位才能使所有的点全部连通。

输入格式

第一行输入两个正整数 m 和 n。

以下若干行每行四个正整数 x1,y1,x2,y2,表示第 x1 行第 y1 列的点和第 x2 行第 y2 列的点已经有连线。

输入保证|x1−x2|+|y1−y2|=1。

输出格式

输出使得连通所有点还需要的最小花费。

数据范围

1≤m,n≤1000
0≤已经存在的连线数≤10000

输入样例:
2 2
1 1 2 1
输出样例:
3

 解析:AcWing 1144. 连接格点(算法提高课) - AcWing

 

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;
typedef long long LL;
const int N = 1e3+10, M = 2 * N * N;
int n, m,k;

int fa[N * N],idx[N][N];
struct st {
	int a, b, c;
}e[M];

int find(int a) {
	if (fa[a] == a)return fa[a];
	return fa[a] = find(fa[a]);
}

void get() {
	int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 }, dw[4] = { 1,2,1,2 };
	for (int z = 0; z < 2; z++) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				for (int u = 0; u < 4; u++) {
					if (u % 2 == z) {
						int x = i + dx[u], y = j + dy[u], w = dw[u];
						if (x && x <= n && y && y <= m) {
							int a = idx[i][j], b = idx[x][y];
							if (a < b)e[++k] = { a,b,w };
						}
					}
				}
			}
		}
	}
}

int main() {
	cin >> n >> m;
	for (int i = 1,t=1; i <= n; i++) {
		for (int j = 1; j <= m; j++,t++) {
			idx[i][j] = t;
		}
	}
	for (int i = 1; i <= n * m; i++)
		fa[i] = i;
	int x1, y, x2, y2;
	while (cin >> x1 >> y >> x2 >> y2) {
		fa[find(idx[x1][y])] = find(idx[x2][y2]);
	}
	get();
	int ans = 0;
	for (int i = 1; i <= k; i++) {
		int a = find(e[i].a), b = find(e[i].b), w = e[i].c;
		if (a != b) {
			fa[a] = b;
			ans += w;
		}
	}
	cout << ans << endl;
	return 0;
}

你可能感兴趣的:(#,最小生成树,算法,矩阵,数据结构,图论)