河南理工大学oj 1704 祈福天津

1704: 祈福天津

时间限制: 1 Sec   内存限制: 128 MB
题目描述
8 12 日夜间 23 30 分左右, 天津 市滨海新区第五大街与跃进路交口的瑞海公司危险品仓库突发连环爆炸。不仅伤亡了许多人,也造成了巨大损失。在这场灾难中,我们的消防官兵赶到现场救援时,许多发生了不幸。“最帅的逆行”感动了无数的人,在这里,让我们为在现场救援的和失联的消防官兵祈福,为群众祈福。为天津祈福,天佑天津。
现在
*** 地区的消防官兵因为需要日常训练,需要在训练地方架设水管,为了提高训练强度,一般训练的地区高度是不一样的,我们暂时把它们分成几个区域,例如: 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; 
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值