NEFU-越狱(Kruskal,建图技巧)

Contest (nefu.edu.cn)

Description

有一批人质关在一个n*m的“网格”监狱中,每个网格中关押着一名人质,每个格子四面都是混凝土墙壁,作为超级英雄的你要去解救这批人质,已知破坏每一堵墙的花费,求解救所有人质的最小花费。
   

Input

T组数据,第一行一个数字T,第二行两个数 n,m(n,m<=500),然后有一个(n+1)*m的矩阵,表示的是整个监狱的所有横向的墙需要的花费,然后是一个n*(m+1)矩阵,表示整个监狱的所有纵向的墙的花费,矩阵里的数字都小于100且都是整数。

Output

对于每一个样例,输出 最小花费。

Sample Input

1
2 3
1 1 1
1 1 1
1 1 1
1 1 1 1
1 1 1 1

Sample Output

6

Hint

 
  

Source

解析:

提供几个样例,其中第三个样例的情况我第一次没想到

1
2 3
2 2 2
1 1 1
2 2 2
2 1 1 2
2 1 1 2


2 3
2 2 2
3 1 3
2 2 2
2 4 1 2
2 1 2 2


2 3
2 2 2
3 6 3
2 2 2
2 4 1 2
2 2 2 2
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;
typedef long long LL;
const int N = 5e2 + 5,M=1e6+1000;
int n, m;
int arr[2][N][N], idx[N][N];
struct e {
	int a, b, c;
}e[3 * N * N];
LL fa[M];

int cmp(const struct e& a, const struct e& b) {
	return a.c < b.c;
}

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

int main() {
	for (int i = 0, t = 0; i <= N - 2; i++) {
		for (int j = 0; j <= N - 2; j++, t++) {
			idx[i][j] = t;
		}
	}
	int T;
	cin >> T;
	while (T--) {
		int cnt = 0;
		scanf("%d%d", &n, &m);
		for (int i = 0; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				scanf("%d", &arr[0][i][j]);
				if (i == 0) {
					e[++cnt] = { 0,idx[i + 1][j],arr[0][i][j] };
				}
				else if (i == n) {
					e[++cnt] = { 0,idx[i][j],arr[0][i][j] };
				}
				else {
					e[++cnt] = { idx[i][j],idx[i + 1][j],arr[0][i][j]};
				}
			}
		}
		for (int i = 1; i <= n; i++) {
			for (int j = 0; j <= m; j++) {
				scanf("%d", &arr[1][i][j]);
				if (j == 0) {
					e[++cnt] = { 0,idx[i][j+1],arr[1][i][j] };
				}
				else if (j == m) {
					e[++cnt] = { 0,idx[i][j],arr[1][i][j] };
				}
				else {
					e[++cnt] = { idx[i][j],idx[i][j + 1],arr[1][i][j]};
				}
			}
		}
		sort(e + 1, e + 1 + cnt, cmp);
		for (int i = 0; i <= n; i++) {
			for (int j = 0; j <= m; j++)
				fa[idx[i][j]] = idx[i][j];
		}
		LL ans = 0;
		for (int i = 1; i <= cnt; i++) {
			int a = find(e[i].a), b = find(e[i].b);
			LL w = e[i].c;
			if (a != b) {
				ans += w;
				
				fa[a] = b;
			}
		}
		cout << ans << endl;
	}
	return 0;
}

你可能感兴趣的:(#,最小生成树,算法,最小生成树)