十分简单的并查集问题,注意建图的方式
#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; }
时间: 2024-10-08 10:19:54