• sss


    <更新提示>

    <第一次更新>


    <正文>

    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
    ",dis[n]);
    	return 0;
    }
    

    <后记>

  • 相关阅读:
    VlanTrunk
    2015届互联网名企校招网址一览表
    The declared package does not match the expected package
    经典的算法网站
    Nutch
    JTable只要一双击就进入编辑状态,禁止的方法实现
    Java通过JDBC链接数据库,数据库中wen
    Cisco Packet Tracer的使用(一)
    Nutch安装的几个网址
    面试经
  • 原文地址:https://www.cnblogs.com/Parsnip/p/10360838.html
Copyright © 2020-2023  润新知