CodeForces_1422D Returning Home(最短路)

sigh_發表於2020-10-05

Returning Home

time limit per test:2 seconds
memory limit per test:256 megabytes

Problem Description

Yura has been walking for some time already and is planning to return home. He needs to get home as fast as possible. To do this, Yura can use the instant-movement locations around the city.

Let’s represent the city as an area of n × n n×n n×n square blocks. Yura needs to move from the block with coordinates ( s x , s y ) (s_x,s_y) (sx,sy) to the block with coordinates ( f x , f y ) (f_x,f_y) (fx,fy). In one minute Yura can move to any neighboring by side block; in other words, he can move in four directions. Also, there are m m m instant-movement locations in the city. Their coordinates are known to you and Yura. Yura can move to an instant-movement location in no time if he is located in a block with the same coordinate x x x or with the same coordinate y y y as the location.

Help Yura to find the smallest time needed to get home.

Input

The first line contains two integers n n n and m m m — the size of the city and the number of instant-movement locations ( 1 ≤ n ≤ 1 0 9 1≤n≤10^9 1n109, 0 ≤ m ≤ 1 0 5 0≤m≤10^5 0m105).

The next line contains four integers s x s_x sx s y s_y sy f x f_x fx f y f_y fy — the coordinates of Yura’s initial position and the coordinates of his home ( 1 ≤ s x , s y , f x , f y ≤ n 1≤s_x,s_y,f_x,f_y≤n 1sx,sy,fx,fyn).

Each of the next m lines contains two integers x i x_i xi y i y_i yi — coordinates of the i-th instant-movement location ( 1 ≤ x i , y i ≤ n ) (1≤x_i,y_i≤n) (1xi,yin).

Output

In the only line print the minimum time required to get home.

Sample Input

5 3
1 1 5 5
1 2
4 1
3 3

Sample Output

5

題意

在一個n*n大小的地圖中,初始在位置 ( s x , s y ) (s_x,s_y) (sx,sy),目標位置為 ( f x , f y ) (f_x, f_y) (fx,fy)。每分鐘可以向上下左右的地圖內區域移動一格。在地圖中有m個瞬移位置,當與這些位置處於同一行或同一列時,可以選擇瞬間傳送到該位置。求最快需要多久到達目標位置。

思路

最短路的最後一步一定是從初始位置或瞬移位置走到目標位置。
可以由瞬移位置的同行或同列瞬間傳送至瞬移位置,所以額外建 2 ∗ m 2*m 2m個點, m m m個點代表 x = x i x=x_i x=xi m m m個點代表 y = y i y=y_i y=yi(將代表 x = x i x=x_i x=xi的m個點按升序排列,y同理)。
兩個瞬移點之間的轉移代價主要看其橫縱座標之差。

建圖:
從 初始位置/瞬移位置連邊 到 目標位置 ,代價為兩點間的距離。
x = x i x=x_i x=xi x = x i − 1 x = x_{i-1} x=xi1, x = x i + 1 x=x_{i+1} x=xi+1,代價為 x i − x i − 1 x_i-x_{i-1} xixi1 x i + 1 − x i x_{i+1}-x_i xi+1xi
從 初始位置 到 x = x i x=x_i x=xi,代價為 a b s ( s x − x i ) abs(s_x-x_i) abs(sxxi)
從 瞬移位置 j j j x = x j x = x_j x=xj,代價為0。
y = y i y=y_i y=yi x = x i x=x_i x=xi同理建邊,同時都為雙向邊。

建完圖後跑最短路即可。

#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<set>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-6
  
using namespace std;
typedef long long LL;
typedef pair<double, int> P;
const int maxn = 300100;
const int mod = 1000000007;
struct node{
    int to, w;
    node(){}
    node(int a, int b):to(a),w(b){}
};
int x[maxn], y[maxn], a[maxn], b[maxn], dis[maxn];
vector<node> g[maxn];
int dijkstra(int n);
void add(int fr, int to, int w);

int main()
{
    int n, m, sx, sy, fx, fy, i, j, k;
    scanf("%d %d", &n, &m);
    scanf("%d %d %d %d", &sx, &sy, &fx, &fy);
    add(0, 3*m+1, abs(sx-fx)+abs(sy-fy));
    for(i=1;i<=m;i++){
        scanf("%d %d", &x[i], &y[i]);
        a[i] = x[i], b[i] = y[i];
    }
    sort(a+1, a+1+m);
    sort(b+1, b+1+m);
    for(i=1;i<=m;i++){
        add(0, i+m, abs(sx-a[i]));
        add(0, i+2*m, abs(sy-b[i]));
        if(i!=1){
            add(i+m, i+m-1, abs(a[i]-a[i-1]));
            add(i+2*m, i+2*m-1, abs(b[i]-b[i-1]));
        }
        if(i!=m){
            add(i+m, i+m+1, abs(a[i]-a[i+1]));
            add(i+2*m, i+2*m+1, abs(b[i]-b[i+1]));
        }
    }
    for(i=1;i<=m;i++){
        add(i, 3*m+1, abs(x[i]-fx)+abs(y[i]-fy));
        int pos = lower_bound(a+1, a+1+m, x[i])-a;
        add(i, pos+m, 0), add(pos+m, i, 0);
        pos = lower_bound(b+1, b+1+m, y[i])-b;
        add(i, pos+2*m, 0), add(pos+2*m, i, 0);
    }
    printf("%d\n", dijkstra(3*m+1));
    return 0;
}

void add(int fr, int to, int w)
{
    g[fr].push_back(node(to, w));
}

int dijkstra(int n)
{
    for(int i=0;i<=n;i++)
        dis[i] = 2e9;
    dis[0] = 0;
    priority_queue<P,vector<P>, greater<P> > que;
    que.push(P(dis[0], 0));
    while(!que.empty())
    {
        P p = que.top();que.pop();
        int u = p.second, v, w;
        if(p.first > dis[u])continue;
        for(int i=0;i<g[u].size();i++){
            v = g[u][i].to, w = g[u][i].w;
            if(dis[v] > dis[u]+w){
                dis[v] = dis[u]+w;
                que.push(P(dis[v], v));
            }
        }
    }
    return dis[n];
}

相關文章