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
 
按题意i号点到j号点的距离是min(|xi-xj|,|yi-yj|),我们可以将其转化成两条边,一条权值为|xi-xj|,一条权值为|yi-yj|,这显然是没问题的。
那么问题就转化成一维问题,如何连最少的边,我们发现按维排序每次将相邻的点连边即可。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
    if(head==tail) {
        int l=fread(buffer,1,BufferSize,stdin);
        tail=(head=buffer)+l;
    }
    return *head++;
}
inline int read() {
    int x=0,f=1;char c=Getchar();
    for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=200010;
const int maxm=800010;
const int inf=1e9;
struct Dijkstra {
    int n,m,d[maxn],done[maxn],first[maxn],next[maxm];
    struct Edge {int from,to,dist;}edges[maxm];
    struct HeapNode {
        int u,d;
        bool operator < (const HeapNode& ths) const {return d>ths.d;}
    };
    void init(int n) {
        this->n=n;m=1;
    }
    void AddEdge(int u,int v,int w) {
        edges[m]=(Edge){u,v,w};next[m]=first[u];first[u]=m++;
    }
    priority_queue<HeapNode> Q;
    void solve(int s) {
        rep(i,1,n) d[i]=inf;
        d[s]=0;Q.push((HeapNode){s,0});
        while(!Q.empty()) {
            int x=Q.top().u;Q.pop();
            if(done[x]) continue;done[x]=1;
            ren {
                Edge& e=edges[i];
                if(d[e.to]>d[x]+e.dist) {
                    d[e.to]=d[x]+e.dist;
                    Q.push((HeapNode){e.to,d[e.to]});
                }
            }
        }
    }
}sol;
struct Point {
    int x,y,id;
}A[maxn];
bool cmp1(Point a,Point b) {return a.x<b.x;}
bool cmp2(Point a,Point b) {return a.y<b.y;}
int main() {
    int n=read();sol.init(n);
    rep(i,1,n) A[A[i].id=i].x=read(),A[i].y=read();
    sort(A+1,A+n+1,cmp1);
    rep(i,1,n) {
        if(i!=1) sol.AddEdge(A[i].id,A[i-1].id,A[i].x-A[i-1].x);
        if(i!=n) sol.AddEdge(A[i].id,A[i+1].id,A[i+1].x-A[i].x);
    }
    sort(A+1,A+n+1,cmp2);
    rep(i,1,n) {
        if(i!=1) sol.AddEdge(A[i].id,A[i-1].id,A[i].y-A[i-1].y);
        if(i!=n) sol.AddEdge(A[i].id,A[i+1].id,A[i+1].y-A[i].y);
    }
    sol.solve(1);printf("%d\n",sol.d[n]);
    return 0;
}
View Code

 

posted @ 2015-11-29 20:51  wzj_is_a_juruo  阅读(289)  评论(0编辑  收藏  举报