1704: 祈福天津
时间限制: 1 Sec 内存限制: 128 MB
题目描述
8
月
12
日夜间
23
:
30
分左右,
天津
市滨海新区第五大街与跃进路交口的瑞海公司危险品仓库突发连环爆炸。不仅伤亡了许多人,也造成了巨大损失。在这场灾难中,我们的消防官兵赶到现场救援时,许多发生了不幸。“最帅的逆行”感动了无数的人,在这里,让我们为在现场救援的和失联的消防官兵祈福,为群众祈福。为天津祈福,天佑天津。
现在 *** 地区的消防官兵因为需要日常训练,需要在训练地方架设水管,为了提高训练强度,一般训练的地区高度是不一样的,我们暂时把它们分成几个区域,例如: A 区域是练习攀爬的地方, B 区域练习跑步, C 区域是战士们休闲区域。我们的所有区域可以看成一个 N 行 M 列的矩阵。我们不考虑每个区域内需要架设多少水管。我们只考虑将这两个区域连接起来需要的水管长度,这个长度就是这两个区域的高度差。一个区域只能跟它上下左右四块相邻的区域相连通,我们现在想知道最少还需要多长的水管可以连接所有区域。
现在 *** 地区的消防官兵因为需要日常训练,需要在训练地方架设水管,为了提高训练强度,一般训练的地区高度是不一样的,我们暂时把它们分成几个区域,例如: A 区域是练习攀爬的地方, B 区域练习跑步, C 区域是战士们休闲区域。我们的所有区域可以看成一个 N 行 M 列的矩阵。我们不考虑每个区域内需要架设多少水管。我们只考虑将这两个区域连接起来需要的水管长度,这个长度就是这两个区域的高度差。一个区域只能跟它上下左右四块相邻的区域相连通,我们现在想知道最少还需要多长的水管可以连接所有区域。
输入
处理到文件结束,第一行有一个数字
T
,代表输入的样例组数。然后每组数据第一行是两个正整数
N
,
M(0<N,M<1000)
,接下来
N
行,每行
M
个数字,数字用空格分开,每个数字是指区域的高度,这个高度不会超过
100
。
输出
输出最少还需要多长的水管。
样例输入
1 2 3 34 56 56 12 23 4
样例输出
74
思路:只有相邻的两块区域才能相连,样例输入中能相连的只有34-56;56-56;12-23;23-4;34-12;56-23;56-4;求最小生成树即可。
代码:
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; struct record { int s,e; double w; }num[3000000]; bool cmp(record a,record b) { return a.w<b.w; } int per[3000000],n,m; int a[1100][1100]; int init() { for(int i=1;i<=n*m;i++) { per[i]=i; } } int find(int x) { int r; r=x; while(r!=per[r]) { r=per[r]; } per[x]=r; return r; } bool join(int x,int y) { int fx=find(x); int fy=find(y); if(fx!=fy) { per[fx]=fy; return true; } return false; } int main() { int t,i,j,k; int sum,d; scanf("%d",&t); while(t--) { k=0;sum=0; scanf("%d%d",&n,&m); init(); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { scanf("%d",&a[i][j]); } } for(i=1;i<=n;i++) { for(j=2;j<=m;j++) { d=abs(a[i][j]-a[i][j-1]); num[k].s=(i-1)*m+j-1; num[k].e=(i-1)*m+j; num[k].w=d; k++; } } for(j=1;j<=m;j++) { for(i=2;i<=n;i++) { d=abs(a[i][j]-a[i-1][j]); num[k].s=(i-1)*m+j; num[k].e=(i-2)*m+j; num[k].w=d; k++; } } sort(num,num+k,cmp); for(i=0;i<k;i++) { if(join(num[i].s,num[i].e)) { sum+=num[i].w; } } printf("%d\n",sum); } return 0; }