• 老oj曼哈顿最小生成树


    Description

    平面坐标系xOy内,给定n个顶点V = (x , y)。对于顶点u、v,u与v之间的距离d定义为|xu – xv| + |yu – yv|
    你的任务就是求出这n个顶点的最小生成树。

    Input

    第一行一个正整数n,表示定点个数。
    接下来n行每行两个正整数x、y,描述一个顶点。

    Output

    只有一行,为最小生成树的边的距离和。

    Sample Input

    4
    1 0
    0 1
    0 -1
    -1 0
    
    

    Sample Output

    6
    
    [数据约定]
    对于30%的数据n <= 2000;
    对于50%的数据n <= 5000;
    对于100%的数据n <= 50000;
    0 <= x, y <= 100000。

    题解:http://blog.csdn.net/acm_cxlove/article/details/8890003
    code:
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define maxn 50005
     7 #define inf 1061109567
     8 using namespace std;
     9 char ch;
    10 bool ok;
    11 void read(int &x){
    12     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    13     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    14     if (ok) x=-x;
    15 }
    16 int n,m,ans=0;
    17 struct Point{
    18     int x,y,d,id;
    19 }point[maxn],tmp[maxn];
    20 bool cmp1(Point a,Point b){
    21     if (a.x!=b.x) return a.x>b.x;
    22     return a.y>b.y;
    23 }
    24 int calc(Point a,Point b){return abs(a.x-b.x)+abs(a.y-b.y);}
    25 struct Edge{
    26     int u,v,c;
    27 }edge[maxn<<2];
    28 bool cmp2(Edge a,Edge b){return a.c<b.c;}
    29 int cntd,d[maxn];
    30 struct DATA{
    31     int val,pos;
    32     void init(){val=inf,pos=-1;}
    33     void update(DATA b){if (val>b.val) val=b.val,pos=b.pos;}
    34 };
    35 struct bit{
    36     #define lowbit(x) ((x)&(-(x)))
    37     DATA node[maxn];
    38     void init(){for (int i=1;i<=cntd;i++) node[i].init();}
    39     void insert(int x,DATA p){
    40         x=cntd-x+1;
    41         for (int i=x;i<=cntd;i+=lowbit(i)) node[i].update(p);
    42     }
    43     int query(int x){
    44         x=cntd-x+1;
    45         DATA ans; ans.init();
    46         for (int i=x;i;i-=lowbit(i)) ans.update(node[i]);
    47         return ans.pos;
    48     }
    49 }T;
    50 void prepare(){
    51     for (int i=1;i<=n;i++) d[i]=point[i].y-point[i].x;
    52     sort(d+1,d+n+1),cntd=unique(d+1,d+n+1)-d-1;
    53     for (int i=1;i<=n;i++) point[i].d=lower_bound(d+1,d+cntd+1,point[i].y-point[i].x)-d;
    54     sort(point+1,point+n+1,cmp1);
    55     T.init();
    56     for (int i=1;i<=n;i++){
    57         int u=point[i].id,v=T.query(point[i].d);
    58         if (v!=-1) edge[++m]=(Edge){u,v,calc(tmp[u],tmp[v])};
    59         T.insert(point[i].d,(DATA){point[i].x+point[i].y,u});
    60     }
    61 }
    62 int fa[maxn];
    63 int find(int x){return x==fa[x]?fa[x]:fa[x]=find(fa[x]);}
    64 int main(){
    65     read(n);
    66     for (int i=1;i<=n;i++) read(point[i].x),read(point[i].y),point[i].id=i;
    67     for (int i=1;i<=n;i++) tmp[i]=point[i]; prepare();
    68     for (int i=1;i<=n;i++) point[i].x=tmp[i].y,point[i].y=tmp[i].x,point[i].id=i; prepare();
    69     for (int i=1;i<=n;i++) point[i].x=-tmp[i].y,point[i].y=tmp[i].x,point[i].id=i; prepare();
    70     for (int i=1;i<=n;i++) point[i].x=tmp[i].x,point[i].y=-tmp[i].y,point[i].id=i; prepare();
    71     sort(edge+1,edge+m+1,cmp2);
    72     for (int i=1;i<=n;i++) fa[i]=i;
    73     for (int i=1,cnt=0;i<=m&&cnt<n;i++)
    74         if (find(edge[i].u)!=find(edge[i].v)) 
    75             fa[find(edge[i].u)]=find(edge[i].v),cnt++,ans+=edge[i].c;
    76     printf("%d
    ",ans);
    77     return 0;
    78 }


  • 相关阅读:
    程序员的希波克拉底誓言[精华]
    怎样成为优秀的软件模型设计者
    C#中Delegate浅析与思考
    程序员是一个美好的职业[精华]
    hdu 1421(搬寝室)
    hdu 4022(map一对多)
    hdu 1114(完全背包)
    hdu 1159(最长公共子序列)
    hdu 2844(多重背包)
    hdu 1257(最长递增子序列)
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5127222.html
Copyright © 2020-2023  润新知