题目大意:平面上的n个点,(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用
题解:首先,忽视min,直接建两条边即可。考虑到从x1->x2的路径,直达一定比绕过另一个点短(从式子很容易看出来),于是按x/y排两次序,相邻的连边即可
我的收获:这个似乎是常见的套路……
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define M 200010
#define INF 1e60
#define pii pair<long long,int>
int n,t,head[M];
long long dis[M];
bool vis[M];
struct point{int x,y,id;}a[M];
struct edge{int to,val,nex;}e[M*4];
priority_queue<pii,vector<pii>,greater<pii> > q;
bool cmpx(point a,point b){return a.x<b.x;}
bool cmpy(point a,point b){return a.y<b.y;}
void add(int u,int v,int z){e[t]=(edge){v,z,head[u]};head[u]=t++;}
void dijkstra()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) dis[i]=INF;
dis[1]=0;q.push(make_pair(0,1));
while(!q.empty())
{
int u=q.top().second;q.pop();
if(vis[u]) continue;vis[u]=1;
for(int i=head[u];i!=-1;i=e[i].nex){
int v=e[i].to;
if(dis[v]>dis[u]+e[i].val) dis[v]=dis[u]+e[i].val,q.push(make_pair(dis[v],v));
}
}
}
void work()
{
sort(a+1,a+n+1,cmpx);
for(int i=1;i<n;i++) add(a[i].id,a[i+1].id,a[i+1].x-a[i].x),add(a[i+1].id,a[i].id,a[i+1].x-a[i].x);
sort(a+1,a+n+1,cmpy);
for (int i=1;i<n;i++) add(a[i].id,a[i+1].id,a[i+1].y-a[i].y),add(a[i+1].id,a[i].id,a[i+1].y-a[i].y);
dijkstra();
printf("%lld\n",dis[n]);
}
void init()
{
t=1;memset(head,-1,sizeof(head));
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i;
}
int main()
{
init();
work();
return 0;
}
457

被折叠的 条评论
为什么被折叠?



