当前位置: 首页 > news >正文

『The Captain 最短路建图优化』


The Captain(BZOJ 4152)

Description

给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。

Input Format

第一行包含一个正整数n(2<=n<=200000),表示点数。
接下来n行,每行包含两个整数xi,yi(0<=xi,yi<=10^9),依次表示每个点的坐标。

Output Format

一个整数,即最小费用。

Sample Input

5  
2 2  
1 1  
4 5  
7 1  
6 7

Sample Output

2

解析

假如说我们直接将平面中的每一个点视为图中的每一个点的话,这就是一道最短路问题。但是显而易见的是我们需要连\(n^2\)条边,这是一定会超时的,主要考虑如何建图优化。

手推几个样例可以发现图中有很多无用的边存在,我们考虑证明什么情况下的连边是不必要的。

证明:
对于任意两点\(P,Q\),其距离为\(\min\{\Delta x,\Delta y\}\).

  • 距离取\(\Delta x\)
    假如在横坐标意义上\(P,Q\)有中间点\(M\).
  1. \(PM\)\(\Delta x_{pm}\)\(MQ\)\(\Delta x_{mq}\),则\(PQ\)连边和\(PM\)\(MQ\)等价.
  2. \(PM\)\(\Delta x_{pm}\)\(MQ\)\(\Delta y_{mq}\),由于\(\Delta y_{mq}<\Delta x_{mq}\)\(PQ\)连边大于\(PM\)\(MQ\).
  3. \(PM\)\(\Delta y_{pm}\)\(MQ\)\(\Delta x_{mq}\),由于\(\Delta y_{pm}<\Delta x_{pm}\)\(PQ\)连边大于\(PM\)\(MQ\).
  4. \(PM\)\(\Delta y_{pm}\)\(MQ\)\(\Delta y_{mq}\),由于\(\Delta y_{pm}<\Delta x_{pm}\)\(\Delta y_{mq}<\Delta x_{mq}\)\(PQ\)连边大于\(PM\)\(MQ\).
    所以,当\(P,Q\)距离取\(\Delta x\),且横坐标意义上\(P,Q\)有中间点\(M\)时,\(PQ\)连边一定不能对最优解造成贡献。
  • 距离取\(\Delta y\)
    假如在纵坐标意义上\(P,Q\)有中间点\(M\),同理\(PQ\)连边一定不能对最优解造成贡献。

得出结论:\(P,Q\)距离取\(\Delta x\),且横坐标意义上\(P,Q\)有中间点\(M\),或者距离取\(\Delta y\),纵坐标意义上\(P,Q\)有中间点\(M\)时,\(PQ\)连边一定不能对最优解造成贡献

那么这就是不必要连的边。相反,则任意两点\(U,V\)距离取\(\Delta x\),且横坐标意义上\(U,V\)相邻,或者\(U,V\)距离取\(\Delta y\),且纵坐标意义上\(U,V\)相邻时,\(U,V\)连边是必要的

那么我们把必要的边连起来就行了,这样的边至多有\(2n\)条,堆优化\(Dijkstra\)解决最短路问题。

\(Code:\)



#include<bits/stdc++.h>
using namespace std;
const int N=200000+80;
struct node{int num,x,y;}p[N];
struct edge{int ver,val,next;}e[N*4];
int n,t,Last[N*4],dis[N],vis[N];
inline bool cmp1(node p1,node p2){return p1.x<p2.x;}
inline bool cmp2(node p1,node p2){return p1.y<p2.y;}
inline bool check1(node p1,node p2){return p2.x-p1.x<=abs(p1.y-p2.y);}
inline bool check2(node p1,node p2){return p2.y-p1.y<abs(p1.x-p2.x);}
inline void insert(int x,int y,int v)
{
    e[++t].val=v;e[t].ver=y;
    e[t].next=Last[x];Last[x]=t;
}
inline void input(void)
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&p[i].x,&p[i].y);
        p[i].num=i;
    }
}
inline void init(void)
{
    sort(p+1,p+n+1,cmp1);
    for(int i=1;i<n;i++)
    {
        if(check1(p[i],p[i+1]))
            insert(p[i].num,p[i+1].num,p[i+1].x-p[i].x),insert(p[i+1].num,p[i].num,p[i+1].x-p[i].x);;
    }
    sort(p+1,p+n+1,cmp2);
    for(int i=1;i<n;i++)
    {
        if(check2(p[i],p[i+1]))
            insert(p[i].num,p[i+1].num,p[i+1].y-p[i].y),insert(p[i+1].num,p[i].num,p[i+1].y-p[i].y);
    }
}
inline void dijkstra(void)
{
    memset(dis,0x3f,sizeof dis);
    priority_queue< pair<int,int>,vector< pair<int,int> >,greater< pair<int,int> > >Heap;
    dis[1]=0;Heap.push(make_pair(0,1));
    while(!Heap.empty())
    {
        int temp=Heap.top().second;
        Heap.pop();
        if(vis[temp])continue;
        vis[temp]=true;
        for(int i=Last[temp];i;i=e[i].next)
        {
            if(dis[e[i].ver]>dis[temp]+e[i].val)
            {
                dis[e[i].ver]=dis[temp]+e[i].val;
                Heap.push(make_pair(dis[e[i].ver],e[i].ver));
            }
        }
    }
}
int main(void)
{
    input();
    init();
    dijkstra();
    printf("%d\n",dis[n]);
    return 0;
}


转载于:https://www.cnblogs.com/Parsnip/p/10360838.html

相关文章:

  • 各种编码格式转换
  • Kali学习笔记40:SQL手工注入(2)
  • Ocelot 资源汇总
  • SSH端口号修改并进行远程访问
  • scrapy爬取知乎某个问题下的所有图片
  • string.intern
  • Servlet 知识点汇总
  • C# 函数1 (函数的定义)
  • XSS 漏洞介绍
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • 端性能优化方法
  • JAVA之Break Continue 浅析
  • [SRM603] WinterAndSnowmen
  • JS高级学习笔记(1)- 基本数据类型 和 强制类型转换
  • 记账程序及GitHub学习记录
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • Angular 4.x 动态创建组件
  • C++类中的特殊成员函数
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • magento2项目上线注意事项
  • 产品三维模型在线预览
  • 构建工具 - 收藏集 - 掘金
  • 你不可错过的前端面试题(一)
  • 爬虫模拟登陆 SegmentFault
  • 普通函数和构造函数的区别
  • 前端_面试
  • 入门级的git使用指北
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 网络应用优化——时延与带宽
  • 一、python与pycharm的安装
  • #Linux(make工具和makefile文件以及makefile语法)
  • (003)SlickEdit Unity的补全
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (三)uboot源码分析
  • (十八)SpringBoot之发送QQ邮件
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (转)3D模板阴影原理
  • (转)fock函数详解
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • ***原理与防范
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .Net IOC框架入门之一 Unity
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • /*在DataTable中更新、删除数据*/
  • /bin/bash^M: bad interpreter: No such file or directory
  • ?
  • @Autowired多个相同类型bean装配问题
  • [ CTF ]【天格】战队WriteUp- 2022年第三届“网鼎杯”网络安全大赛(青龙组)
  • [100天算法】-不同路径 III(day 73)
  • [ACM] hdu 1201 18岁生日