【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
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\n",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])); } }
| 欢迎来原网站坐坐! >原文链接<