十分简单的并查集问题,注意建图的方式
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1005;
const int maxd = 5000005;
const int dir[2][2] = {{0,1},{1,0}};
int n,m,mat[maxn][maxn],cnt,fa[maxd];
struct Node{
int u,v,d;
friend bool operator < (Node p,Node q){
return p.d < q.d;
}
}edge[maxd];
void init(){
for(int x = 0; x < n; x++)
for(int y = 0; y < m; y++){
for(int d = 0; d < 2; d ++){
int xx = x + dir[d][0];
int yy = y + dir[d][1];
if(xx >= 0 && xx < n && yy >= 0 && yy < m){
edge[cnt].u = x * m + y;
edge[cnt].v = xx * m + yy;
edge[cnt].d = abs(mat[xx][yy] - mat[x][y]);
cnt ++;
}
}
}
}
int find_father(int u){
return fa[u] == u ? u : fa[u] = find_father(fa[u]);
}
int main(){
int T,Case = 1;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
cnt = 0;
int t = n * m;
for(int i = 0; i <= t; i ++) fa[i] = i;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d",&mat[i][j]);
init();
sort(edge,edge + cnt);
int ans = 0;
printf("Case #%d:\n",Case++);
for(int i = 0; i < cnt; i++){
int f1 = find_father(edge[i].u);
int f2 = find_father(edge[i].v);
if(f1 != f2){
//printf("%d %d %d\n",edge[i].u,edge[i].v,edge[i].d);
ans += edge[i].d;
fa[f1] = f2;
}
}
printf("%d\n",ans);
}
return 0;
}