zoukankan      html  css  js  c++  java
  • hdu5253 MST

    连接的管道

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2708    Accepted Submission(s): 961


    Problem Description
    老 Jack 有一片农田,以往几年都是靠天吃饭的。但是今年老天格外的不开眼,大旱。所以老 Jack 决定用管道将他的所有相邻的农田全部都串联起来,这样他就可以从远处引水过来进行灌溉了。当老 Jack 买完所有铺设在每块农田内部的管道的时候,老 Jack 遇到了新的难题,因为每一块农田的地势高度都不同,所以要想将两块农田的管道链接,老 Jack 就需要额外再购进跟这两块农田高度差相等长度的管道。

    现在给出老 Jack农田的数据,你需要告诉老 Jack 在保证所有农田全部可连通灌溉的情况下,最少还需要再购进多长的管道。另外,每块农田都是方形等大的,一块农田只能跟它上下左右四块相邻的农田相连通。
     
    Input
    第一行输入一个数字T(T10) ,代表输入的样例组数

    输入包含若干组测试数据,处理到文件结束。每组测试数据占若干行,第一行两个正整数 N,M(1N,M1000) ,代表老 Jack 有N行*M列个农田。接下来 N 行,每行 M 个数字,代表每块农田的高度,农田的高度不会超过100。数字之间用空格分隔。
     
    Output
    对于每组测试数据输出两行:

    第一行输出:"Case #i:"。i代表第i组测试数据。

    第二行输出 1 个正整数,代表老 Jack 额外最少购进管道的长度。
     
    Sample Input
    2 4 3 9 12 4 7 8 56 32 32 43 21 12 12 2 3 34 56 56 12 23 4
     
    Sample Output
    Case #1: 82 Case #2: 74
    一直没做mst结果建图坑惨我了:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1005;
    int f[maxn*maxn];
    short h[maxn][maxn];                                                                                     //height<100,用short节约内存不然会爆(或者用结构体可以少一个r数组)
    int u[2*maxn*maxn],v[2*maxn*maxn],w[2*maxn*maxn],r[2*maxn*maxn];    //最大点数1000*1000,所以最多有2*1000*1000条边
    int fx[4][2]={{-1,0},/*{1,0},*/{0,-1}/*,{0,1}*/};                                           //易得只要求左边相邻和上边相邻的点的距离即可表示出所有的边
    bool cmp(int i,int j)
    {
    return w[i]<w[j];
    }
    int find(int v)
    {
    return f[v]==v?v:f[v]=find(f[v]);
    }
    int main()
    {
    int n,m,i,j,t,k=0;
    scanf("%d",&t);
    while (t--){int p=0,ans=0,ml=0;
    scanf("%d%d",&n,&m);

    for (i=1;i<=n*m;i++) f[i]=i;
    for (i=1;i<=n;i++){
    for (j=1;j<=m;j++){
    scanf("%d",&h[i][j]);
    //cout<<"fuck"<<endl;
    for (int xt=0;xt<2;xt++){
    int dx=i+fx[xt][0];
    int dy=j+fx[xt][1];
    if (dx<1||dy<1||dx>n||dy>m) continue;

    ml++;
    r[++p]=ml;
    u[p]=(i-1)*m+j;                                                             //u,v中存的是点的标号(1,2,3,4,5.......n*m),所以记得将二维坐标转化为一维,就是这里坑死我了= =
    v[p]=(dx-1)*m+dy;
    w[p]=abs(h[i][j]-h[dx][dy]);
    //cout<<u[p]<<" "<<v[p]<<" "<<w[p]<<endl;
    }
    }
    }
    int temp=0;
    sort(r+1,r+p+1,cmp);
    for (i=1;i<=p;i++){
    int e=r[i];
    int x=find(u[e]);
    int y=find(v[e]);
    if (x!=y) {temp++;
    ans+=w[e];
    f[x]=y;
    }
    if (temp==n*m-1) break;
    //for (int ki=1;ki<=n*m;ki++) cout<<f[ki]<<" ";cout<<endl;
    }
    printf("Case #%d: %d ",++k,ans);

    }
    return 0;
    }

  • 相关阅读:
    洛谷P1306 斐波那契公约数
    Codevs 1688 求逆序对(权值线段树)
    poj1006 Biorhythms
    2017-9-2 NOIP模拟赛
    洛谷P1633 二进制
    洛谷P2513 [HAOI2009]逆序对数列
    洛谷P2687 [USACO4.3]逢低吸纳Buy Low, Buy Lower
    洛谷P2285 [HNOI2004]打鼹鼠
    2017-8-31 NOIP模拟赛
    洛谷P2134 百日旅行
  • 原文地址:https://www.cnblogs.com/zzqc/p/6435972.html
Copyright © 2011-2022 走看看