[BZOJ4152][AMPPZ2014]The Captain

bzoj

sol

按照\(x\)\(y\)排序,考虑两个相邻的点之间的距离,显然分步走不会比直接走更劣。

所以按照\(x\)\(y\)排序后,只对相邻的先连边。

\(Dijkstra\)即可。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
#define pli pair<ll,int>
#define mk make_pair
using namespace std;
int gi()
{
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
const int N = 4e5+5;
struct node{int x,y,id;}p[N];
int n,to[N<<1],nxt[N<<1],head[N],cnt,vis[N];ll ww[N<<1],dis[N];
priority_queue<pli,vector<pli>,greater<pli> >Q;
bool cmp_x(node a,node b){return a.x<b.x;}
bool cmp_y(node a,node b){return a.y<b.y;}
void link(int u,int v,ll w)
{
	to[++cnt]=v;nxt[cnt]=head[u];ww[cnt]=w;
	head[u]=cnt;
	to[++cnt]=u;nxt[cnt]=head[v];ww[cnt]=w;
	head[v]=cnt;
}
void dijkstra()
{
	memset(dis,63,sizeof(dis));
	dis[1]=0;Q.push(mk(0,1));
	while (!Q.empty())
	{
		int u=Q.top().second;Q.pop();
		if (vis[u]) continue;vis[u]=1;
		for (int e=head[u];e;e=nxt[e])
			if (dis[to[e]]>dis[u]+ww[e])
				dis[to[e]]=dis[u]+ww[e],Q.push(mk(dis[to[e]],to[e]));
	}
}
int main()
{
	n=gi();
	for (int i=1;i<=n;++i) p[i]=(node){gi(),gi(),i};
	sort(p+1,p+n+1,cmp_x);
	for (int i=1;i<n;++i)
		link(p[i].id,p[i+1].id,p[i+1].x-p[i].x);
	sort(p+1,p+n+1,cmp_y);
	for (int i=1;i<n;++i)
		link(p[i].id,p[i+1].id,p[i+1].y-p[i].y);
	dijkstra();
	printf("%lld\n",dis[n]);return 0;
}
posted @ 2018-03-28 13:57  租酥雨  阅读(173)  评论(0编辑  收藏  举报