\(Solution\)

参考

对于每个点,向唯一有可能与它形成MST的8个点连边,由于是双向单边,所以每个点最多连出4条边(证明见blog

怎么找到一个区域内最近的点?

只考虑y轴右侧45°的区域,其余部分可以通过坐标变换移动到这一区域

设当前点P(x0,y0),这一区域一点P1(x1,y1),满足x1>x0 && y1-x1>y0-x0

那么dis(AB)= y1-y0+x1-x0 = x1+y1-(x0+y0)

这样这一区域内dis(AB)最小的点即 在满足之前条件的点中 x1+y1最小的点

先对x排序;then由于是只查询某个后缀,可以对y-x离散后用树状数组找到最小的x+y

  1. #include<cstdio>
  2. #include<cctype>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define lb(x) (x&-x)
  6. #define gc() getchar()
  7. #define dis(i,j) (std::abs(p[i].x-p[j].x)+std::abs(p[i].y-p[j].y))
  8. const int N=5e4+5;
  9. int n,Enum,fa[N],A[N],ref[N];
  10. struct Point
  11. {
  12. int x,y,id;
  13. inline bool operator <(const Point &a)const {return x==a.x?y<a.y:x<a.x;}
  14. }p[N];
  15. struct Bit_Tree
  16. {
  17. int val[N],pos[N];
  18. inline void Init() {memset(val,0x7f,sizeof val);}
  19. void Update(int p,int v,int vp)
  20. {
  21. for(;p;p-=lb(p))
  22. if(val[p]>v) val[p]=v,pos[p]=vp;
  23. }
  24. int Query(int p,int n)
  25. {
  26. int mn=1<<30,res=-1;
  27. for(;p<=n;p+=lb(p))
  28. if(mn>val[p]) mn=val[p],res=pos[p];
  29. return res;
  30. }
  31. }t;
  32. struct Edge
  33. {
  34. int to,fr,val;
  35. inline bool operator <(const Edge &a)const {return val<a.val;}
  36. }e[N<<2];
  37. inline void AddEdge(int u,int v,int w)
  38. {
  39. e[++Enum].to=v, e[Enum].fr=u, e[Enum].val=w;
  40. }
  41. inline int read()
  42. {
  43. int now=0,f=1;register char c=gc();
  44. for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
  45. for(;isdigit(c);now=now*10+c-'0',c=gc());
  46. return now*f;
  47. }
  48. int Getf(int x)
  49. {
  50. return x==fa[x]?x:fa[x]=Getf(fa[x]);
  51. }
  52. int MST()
  53. {
  54. for(int dir=0;dir<4;++dir)//坐标变换
  55. {//Time1.不变
  56. if(dir==1||dir==3)
  57. for(int i=1;i<=n;++i) std::swap(p[i].x,p[i].y);//T2.T4.关于y=x对称
  58. else if(dir==2)
  59. for(int i=1;i<=n;++i) p[i].x=-p[i].x;//T3.关于x=0对称
  60. std::sort(p+1,p+1+n);
  61. t.Init();
  62. for(int i=1;i<=n;++i) A[i]=ref[i]=p[i].y-p[i].x;
  63. std::sort(A+1,A+1+n);
  64. int m=1; ref[1]=A[1];
  65. for(int i=2;i<=n;++i)
  66. if(A[i]!=A[i-1]) ref[++m]=A[i];
  67. for(int pos,res,i=n;i;--i)
  68. {
  69. pos=std::lower_bound(ref+1,ref+1+m,p[i].y-p[i].x)-ref;
  70. if((res=t.Query(pos,m))!=-1) AddEdge(p[i].id,p[res].id,dis(i,res));
  71. t.Update(pos,p[i].x+p[i].y,i);
  72. }
  73. }
  74. std::sort(e+1,e+1+Enum);
  75. for(int i=1;i<=n;++i) fa[i]=i;
  76. int res=0;
  77. for(int r1,r2,i=1,k=0;i<=Enum;++i)
  78. {
  79. r1=Getf(e[i].fr),r2=Getf(e[i].to);
  80. if(r1!=r2)
  81. {
  82. res+=e[i].val, fa[r1]=r2;
  83. if(++k==n-1) break;
  84. }
  85. }
  86. return res;
  87. }
  88. int main()
  89. {
  90. n=read();
  91. for(int i=1;i<=n;++i) p[i].x=read(),p[i].y=read(),p[i].id=i;
  92. printf("%d",MST());
  93. return 0;
  94. }

BZOJ.2177.曼哈顿最小生成树(Kruskal)的更多相关文章

  1. BZOJ 2177: 曼哈顿最小生成树

    Sol 考了好几次曼哈顿最小生成树,然而一直不会打...这次终于打出来了...神tm调试了2h...好蛋疼... 首先曼哈顿最小生成树有个结论就是讲它每45度分出一个象限,对于每个点,只与每个象限中离 ...

  2. 【BZOJ-2177】曼哈顿最小生成树 Kruskal + 树状数组

    2177: 曼哈顿最小生成树 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 190  Solved: 77[Submit][Status][Discu ...

  3. poj 3241 Object Clustering (曼哈顿最小生成树)

    Object Clustering Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 2640   Accepted: 806 ...

  4. POJ3241 Object Clustering 曼哈顿最小生成树

    题意:转换一下就是求曼哈顿最小生成树的第n-k条边 参考:莫涛大神的论文<平面点曼哈顿最小生成树> /* Problem: 3241 User: 96655 Memory: 920K Ti ...

  5. 模板——最小生成树kruskal算法+并查集数据结构

    并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每 ...

  6. 最小生成树——Kruskal与Prim算法

    最小生成树——Kruskal与Prim算法 序: 首先: 啥是最小生成树??? 咳咳... 如图: 在一个有n个点的无向连通图中,选取n-1条边使得这个图变成一棵树.这就叫“生成树”.(如下图) 每个 ...

  7. 【转】最小生成树——Kruskal算法

    [转]最小生成树--Kruskal算法 标签(空格分隔): 算法 本文是转载,原文在最小生成树-Prim算法和Kruskal算法,因为复试的时候只用到Kruskal算法即可,故这里不再涉及Prim算法 ...

  8. BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )

    不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...

  9. BZOJ.1016.[JSOI2008]最小生成树计数(Matrix Tree定理 Kruskal)

    题目链接 最小生成树有两个性质: 1.在不同的MST中某种权值的边出现的次数是一定的. 2.在不同的MST中,连接完某种权值的边后,形成的连通块的状态是一样的. \(Solution1\) 由这两个性 ...

随机推荐

  1. 基于内容的图片检索CBIR简介

    原文地址:http://blog.csdn.net/davebobo/article/details/53171311 传统的图像检索过程,先通过人工对图像进行文字标注,再利用关键字来检索图像,这种依 ...

  2. 无向图最小割Stoer-Wagner算法学习

    无向连通网络,去掉一个边集可以使其变成两个连通分量则这个边集就是割集,最小割集当然就权和最小的割集. 使用最小切割最大流定理: 1.min=MAXINT,确定一个源点 2.枚举汇点 3.计算最大流,并 ...

  3. CentOS 6.5 rsync+inotify实现数据实时同步备份

    CentOS 6.5 rsync+inotify实现数据实时同步备份 rsync    remote sync 远程同步,同步是把数据从缓冲区同步到磁盘上去的.数据在内存缓存区完成之后还没有写入到磁盘 ...

  4. android手机访问app网页报错:net::ERR_PROXY_CONNECTION_FAILED

    手机访问网页报错:net::ERR_PROXY_CONNECTION_FAILED 手机访问app中嵌入的html网页报错: net::ERR_PROXY_CONNECTION_FAILED 原来是手 ...

  5. http响应头设置

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletExcep ...

  6. 单例模式(懒汉、饿汉、同步锁、static、枚举)实现

    使用前提: 需要频繁的进行创建和销毁的对象,创建对象时耗时过多或耗费资源过多 三要素: 1.构造方法私有化: 2.实例化的变量引用私有化: 3.获取实例的方法共有. 1.饿汉式单例 弊端:在类装载的时 ...

  7. 如何在DOS窗口复制和粘贴命令

    在键盘上按下windows+R键,打开运行窗口. 在“打开”处输入cmd,并按下enter键,打开DOS窗口. 把鼠标移动到DOS窗口标题处,单击鼠标右键,选择属性. 把编辑选项处的“快速编辑模式”勾 ...

  8. ajax相关知识点

    AJAX的概念,即“Asynchronous Javascript And XML” 通过在后台(浏览器的后台)与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个 ...

  9. visual studio 2017 installer 安装包制作过程出现的问题---此安装程序需要.NET Framework 版本 3.5,请安装该版本,然后重新运行此安装程序,可以从Web获得.NET Framework 。要立即做此事吗?

    图一 visual studio 2017 installer 打包完成以后进行安装时,提示信息 “安装此安装程序需要.NET Framework 版本 3.5,请安装该版本,然后重新运行此安装程序, ...

  10. InterruptedException 异常

    当一个方法后面声明可能会抛出InterruptedException 异常时,说明该方法是可能会花一点时间,但是可以取消的方法. 抛InterruptedException的代表方法有: 1. jav ...