zoukankan      html  css  js  c++  java
  • 【BZOJ4152】[AMPPZ2014]The Captain 最短路

    【BZOJ4152】[AMPPZ2014]The Captain

    Description

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

    Input

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

    Output

    一个整数,即最小费用。

    Sample Input

    5
    2 2
    1 1
    4 5
    7 1
    6 7

    Sample Output

    2

    题解:做法很神,也很简洁。

    将所有点按x排序,显然只需要在相邻的点之间连边即可,然后在按y排序做一遍,跑最短路就完事了。

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    #include <utility>
    #define mp(A,B) make_pair(A,B)
    using namespace std;
    const int maxn=200010;
    typedef long long ll;
    struct node
    {
    	int x,y,org;
    }p[maxn];
    int n,cnt;
    int to[maxn<<2],next[maxn<<2],head[maxn],val[maxn<<2];
    bool vis[maxn];
    ll dis[maxn];
    priority_queue<pair<ll,int> > q;
    inline char nc()
    {
    	static char buf[100000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=nc();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=nc();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=nc();
    	return ret*f;
    }
    bool cmpx(const node &a,const node &b)
    {
    	return a.x<b.x;
    }
    bool cmpy(const node &a,const node &b)
    {
    	return a.y<b.y;
    }
    inline void add(int a,int b,int c)
    {
    	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
    	to[cnt]=a,val[cnt]=c,next[cnt]=head[b],head[b]=cnt++;
    }
    int main()
    {
    	n=rd();
    	register int i,u;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<=n;i++)	p[i].x=rd(),p[i].y=rd(),p[i].org=i;
    	sort(p+1,p+n+1,cmpx);
    	for(i=1;i<n;i++)	add(p[i].org,p[i+1].org,p[i+1].x-p[i].x);
    	sort(p+1,p+n+1,cmpy);
    	for(i=1;i<n;i++)	add(p[i].org,p[i+1].org,p[i+1].y-p[i].y);
    	memset(dis,0x3f,sizeof(dis));
    	dis[1]=0,q.push(mp(0,1));
    	while(!q.empty())
    	{
    		u=q.top().second,q.pop();
    		if(vis[u])	continue;
    		if(u==n)
    		{
    			printf("%lld
    ",dis[n]);
    			return 0;
    		}
    		vis[u]=1;
    		for(i=head[u];i!=-1;i=next[i])	if(dis[to[i]]>dis[u]+val[i])
    			dis[to[i]]=dis[u]+val[i],q.push(mp(-dis[to[i]],to[i]));
    	}
    }

     

  • 相关阅读:
    二叉树遍历
    keras简单介绍与使用
    pandas基础使用
    如何在真机装linux(本人在台式机上又添了个硬盘)
    linux下安装kears
    Java Web 环境搭建步骤(超详细,包括前期安装步骤)
    python求范数
    随笔
    【opencv C++ linux】linux下编译含opencv的C++代码
    【论文阅读】DCAN: Deep Contour-Aware Networks for Accurate Gland Segmentation
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7670355.html
Copyright © 2011-2022 走看看