zoukankan      html  css  js  c++  java
  • D:Returning Home-Codeforces Round #675 (Div. 2)

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

    Problem:

    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) square blocks. Yura needs to move from the block with coordinates ((sx,sy)) to the block with coordinates ((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 mm 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) or with the same coordinate (y) as the location.

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

    Input:

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

    The next line contains four integers (sx,sy,fx,fy) — the coordinates of Yura's initial position and the coordinates of his home ((1≤sx,sy,fx,fy≤n)).

    Each of the next mm lines contains two integers (xi,yi) — coordinates of the (i)-th instant-movement location ((1≤xi,yi≤n)).

    Output:

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

    Examples:

    input

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

    output

    5
    

    input

    84 5
    67 59 41 2
    39 56
    7 2
    15 3
    74 18
    22 7
    

    output

    42
    
    Solution:

    因为可以借助location走捷径,所以我们将所有location位置记录后构造无向图,因为任意两个location都是可以互相到达的,所以这里有(m*(m-1)/2)条边,由于m最大为(10^5),显然是无法存下这么大的图的,但是经过分析我们可以发现,假设存在两个点(l(x_1,y_1),r(x_2,y_2)),两点距离为(min(abs(x_1-y_1),abs(x_2-y_2))),如果存在第三个点(k(x_3,y_3))且满足(x1 leq x_3 leq x_2),则有(dis[x_1,x_2] = dis[x_1,x_3] + dis[x_3, x_2]),因此只需要建立(edge[x_1,x_3] 和 edge[x_2,x_3]),考虑(x,y)两个方向,构造图时只需要将所有点按照(x)(y)的坐标排序之后建边即可,构造图之后,在构造图上运行最短路算法,对于起点计算(sx,sy)到每个点的距离,并进行最短路算法,之后计算最短路径加上该点到(fx,fy)的距离取其中的最小值即为答案。

    Code:
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 811111;
    const int inf = 0x3fffff;
    
    typedef long long ll;
    
    struct ad{
        int x, y, a;
        ad(int i, int j, int k) : x(i), y(j), a(k) {}
        ad() : x(0), y(0), a(0) {}
    }loc[maxn];
    
    bool cmp1(ad l, ad r) {
        if(l.x == r.x) return l.y < r.y;
        return l.x < r.x;
    }
    
    bool cmp2(ad l, ad r) {
        if(l.y == r.y) return l.x < r.x;
        return l.y < r.y;
    }
    
    ll first[maxn], nxt[maxn], cnt, v[maxn], w[maxn];
    pair<int, int> poc[maxn];
    ll dis[maxn];
    
    void add(int x, int y, int d) {
        cnt++;
        v[cnt] = y; w[cnt] = d;
        nxt[cnt] = first[x]; first[x] = cnt;
        return;
    }
    
    int main()
    {
        ios_base::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int n, m, sx, sy, fx, fy;
        cin >> n >> m >> sx >> sy >> fx >> fy;
        for(int i = 1; i <= m; ++i) {
            int x, y;
            cin >> x >> y;
            poc[i] = make_pair(x, y);
            loc[i] = ad(x, y, i);
        }
        memset(first, -1, sizeof(first));
        memset(nxt, -1, sizeof(nxt));
        cnt = 0;
        sort(loc + 1, loc + 1 + m, cmp1);
        for(int i = 2; i <= m; ++i) {
            ad la = loc[i - 1];
            int ds = min(abs(loc[i].x - la.x), abs(loc[i].y - la.y));
            add(loc[i].a, la.a, ds);
            add(la.a, loc[i].a, ds);
        }
        sort(loc + 1, loc + 1 + m, cmp2);
        for(int i = 2; i <= m; ++i) {
            ad la = loc[i - 1];
            int ds = min(abs(loc[i].x - la.x), abs(loc[i].y - la.y));
            add(loc[i].a, la.a, ds);
            add(la.a, loc[i].a, ds);
        }
        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> box;
        for(int i = 1; i <= m; ++i) {
            dis[i] = min(abs(sx - poc[i].first), abs(sy - poc[i].second));
            box.push(make_pair(dis[i], i));
        }
        while(!box.empty()) {
            int wd, x;
            wd = box.top().first; x = box.top().second;
            box.pop();
            if(wd != dis[x]) continue;
            for(int i = first[x]; i != -1; i = nxt[i]) {
                int y = v[i];
                int c = w[i];
                if(dis[y] > wd + c) {
                    dis[y] = wd + c;
                    box.push(make_pair(dis[y], y));
                }
            }
        }
        ll ans = abs(sx - fx) + abs(sy - fy);
        for(int i = 1; i <= m; ++i) {
            ans = min(ans, dis[i] + abs(poc[i].first - fx) + abs(poc[i].second - fy));
        }
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    C#中在AxWebBrowser控件注入JS脚本的方法
    C# 操作鼠标移动到指定的屏幕位置方法
    uvm的sequence
    uvm学习杂记
    形参和实参
    gvim中对变量的识别
    验证环境中的program为什么必须是automatic
    FIFO设计验证经验谈
    AMBA总线基础知识简介
    systemverilog中module与program的区别
  • 原文地址:https://www.cnblogs.com/LeafLove/p/13786212.html
Copyright © 2011-2022 走看看