天天看点

Returning Home

​​D - Returning Home ​​

参考:D:Returning Home-Codeforces Round #675 (Div. 2)

最短路的题难点在于建图,这道题的图不是特别难建

思路:对于每一个点,分别与 x 轴和 y 轴上相邻的两个点,连边,然后起点与每一个点连边即可。

//Created by CAD
#include <bits/stdc++.h>

#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define fi first
#define se second
#define mst(name, value) memset(name,value,sizeof(name))
using namespace std;

const int maxn=1e5+5;
pii a[maxn];

int d[maxn];
bool vis[maxn];
vector<pii> g[maxn];
struct node{
    int x,y,id;
}p[maxn];
bool cmp1(const node &a,const node &b){
    return a.x<b.x;
}
bool cmp2(const node &a,const node &b){
    return a.y<b.y;
}
void dij(int s){
    priority_queue<pii,vector<pii>,greater<pii>> q;
    mst(d,0x3f);
    d[s]=0;
    q.push({0,s});
    while(!q.empty()){
        pii now=q.top();
        q.pop();
        vis[now.se]=1;
        for(pii &i:g[now.se]){
            if(vis[i.fi]) continue;
            if(d[i.fi]>now.fi+i.se)
                d[i.fi]=now.fi+i.se,q.push({d[i.fi],i.fi});
        }
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n,m;    cin>>n>>m;
    int sx,sy,fx,fy;cin>>sx>>sy>>fx>>fy;
    for(int i=1;i<=m;++i){
        cin>>a[i].fi>>a[i].se;
        p[i]={a[i].fi,a[i].se,i};
        int w=min(abs(sx-a[i].fi),abs(sy-a[i].se));
        g[0].push_back({i,w});
        g[i].push_back({0,w});
    }
    sort(p+1,p+1+m,cmp1);
    for(int i=1;i<m;++i){
        node &c=p[i],&d=p[i+1];
        int w=min(abs(d.x-c.x),abs(d.y-c.y));
        g[c.id].push_back({d.id,w});
        g[d.id].push_back({c.id,w});
    }
    sort(p+1,p+1+m,cmp2);
    for(int i=1;i<m;++i){
        node &c=p[i],&d=p[i+1];
        int w=min(abs(d.x-c.x),abs(d.y-c.y));
        g[c.id].push_back({d.id,w});
        g[d.id].push_back({c.id,w});
    }
    dij(0);
    int ans=abs(sx-fx)+abs(sy-fy);
    for(int i=1;i<=m;++i)
        ans=min(ans,d[i]+abs(a[i].fi-fx)+abs(a[i].se-fy));
    cout<<ans<<endl;
    return 0;
}