4152 bzoj [AMPPZ2014]ザ・キャプテン
分所与のnに対して定義された平面上の点(X1、Y1)(X2、Y2)有料(| X1-X2 |、| Y1-Y2は|)、ポイント数nに点1からの要求に来最小コスト。
最初に私は実際にはマンハッタン距離の分を取って、これを取ります。。
暴力は、図を構築している\(N ^ 2 \)
の二点を考慮し、缶(| X_1、X_2 | \ \ ) と\(| Y_1-Y_2は| \ ) 重量チャートが最短実行時間に建設されたありますパイプの必要はありませんので、エッジの重みの大きな部分を取ることはない(\分\)\
順に\(| X_1-X_2を| \ ) 重量プラス側で、例えば、3点があります\(I \) 、\(J \) 、\(K \) 、\(X_I \のLeq X - jが\のLeq X_K \) 、次いで\(DIS(I、K) = DIS(I、J)+ DIS(j、k)は\)ので、長辺を構築するためにラインにのみ隣接する2つの点を順序付けることによって、X n点として
に(\ | \)| y_1- Y_2 同様とき重量
最後に実行再度最短
コード。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define R register
#define EN std::puts("")
#define LL long long
inline int read(){
int x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
struct point{
int x,y,id;
}a[200006];
int n;
int fir[200006],nex[800006],to[800006],w[800008],tot;
LL dis[200006];int in[200006];
int dui[200006],size;
inline void push(int x){
dui[size++]=x;
R int i=size-1,fa;
while(i){
fa=i>>1;
if(dis[dui[fa]]<=dis[dui[i]]) return;
std::swap(dui[fa],dui[i]);i=fa;
}
}
inline int pop(){
int ret=dui[0];dui[0]=dui[--size];
R int i=0,ls,rs;
while((i<<1)<size){
ls=i<<1;rs=ls|1;
if(rs<size&&dis[dui[rs]]<dis[dui[ls]]) ls=rs;
if(dis[dui[ls]]>=dis[dui[i]]) break;
std::swap(dui[ls],dui[i]);i=ls;
}
return ret;
}
inline int cmpx(point aa,point bb){return aa.x<bb.x;}
inline int cmpy(point aa,point bb){return aa.y<bb.y;}
inline void add(int x,int y,int z){
to[++tot]=y;w[tot]=z;
nex[tot]=fir[x];fir[x]=tot;
}
inline void dij(){
std::memset(dis,0x3f,sizeof dis);
dis[1]=0;push(1);in[1]=1;
while(size){
R int u=pop();in[u]=0;
for(R int i=fir[u];i;i=nex[i]){
R int v=to[i];
if(dis[v]>dis[u]+w[i]){
dis[v]=dis[u]+w[i];
if(!in[v]) push(v),in[v]=1;
}
}
}
}
int main(){
n=read();
for(R int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].id=i;
std::sort(a+1,a+1+n,cmpx);
for(R 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);
std::sort(a+1,a+1+n,cmpy);
for(R 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);
dij();
std::printf("%lld",dis[n]);
return 0;
}